diff --git a/config/env/all.js b/config/env/all.js index d5656923..6645be80 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -90,9 +90,14 @@ module.exports = { 'public/modules/*/*.js', 'public/modules/*/*[!tests]*/*.js' ], + views: [ + 'public/modules/*/views/*.html', + 'public/modules/*/views/**/*.html' + ], tests: [ 'public/lib/angular-mocks/angular-mocks.js', - 'public/modules/*/tests/*.js' + 'public/modules/*/tests/*.js', + 'public/modules/*/tests/*/*.js', ] } }; diff --git a/karma.conf.js b/karma.conf.js index 7c0203e6..bae0d2ad 100755 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,12 +15,23 @@ module.exports = function(config) { frameworks: ['jasmine'], // List of files / patterns to load in the browser - files: bowerDep.concat(applicationConfiguration.assets.js, applicationConfiguration.assets.tests), + files: bowerDep.concat(applicationConfiguration.assets.js, applicationConfiguration.assets.tests, applicationConfiguration.assets.views), // Test results reporter to use // Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['mocha', 'html', 'progress'], + preprocessors: { + 'public/modules/**/*.html': ['ng-html2js'] + }, + + ngHtml2JsPreprocessor: { + stripPrefix: 'public/', + + // the name of the Angular module to create + moduleName: 'module-templates' + }, + // Web server port port: 9876, diff --git a/package.json b/package.json index 83ec730a..190a403f 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "karma-jasmine": "^0.2.3", "karma-jasmine-html-reporter": "^0.1.8", "karma-mocha-reporter": "^1.1.1", + "karma-ng-html2js-preprocessor": "^0.1.2", "node-mandrill": "^1.0.1" } } diff --git a/public/dist/application.js b/public/dist/application.js index 7a06e50b..4964cdfb 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -574,13 +574,14 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope }; $scope.duplicate = function(form_index){ - var form = $scope.myforms[form_index]; - delete form._id; + var form = _.clone($scope.myforms[form_index]); + form._id = ''; $http.post('/forms', {form: form}) .success(function(data, status, headers){ - // console.log('form duplicated'); + console.log('form duplicated'); $scope.myforms.splice(form_index+1, 0, data); + console.log($scope.myforms[3]._id); }).error(function(errorResponse){ console.log(errorResponse); $scope.error = errorResponse.data.message; @@ -592,7 +593,7 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope console.log($scope.forms.createForm); var form = {}; - form.title = $scope.forms.createForm.$modelValue; + form.title = $scope.forms.createForm.title.$modelValue; form.language = $scope.forms.createForm.language.$modelValue; if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){ @@ -630,32 +631,42 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope 'use strict'; // Forms controller -angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', - function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm) { +angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', 'Auth', + function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm, Auth) { + $scope.authentication = Auth; + $scope.initForm = function(){ + Forms.get({ + formId: $stateParams.formId + }).$promise.then( + //success + function(form){ + $scope.myform = form; - Forms.get({ - formId: $stateParams.formId - }).$promise.then( - //success - function(form){ - $scope.myform = form; + if(!$scope.myform.isLive){ + // Show navbar if form is not public AND user IS loggedin + if($scope.authentication.isAuthenticated()){ + $scope.hideNav = $rootScope.hideNav = false; + } + // Redirect if form is not public user IS NOT loggedin + else { + $scope.hideNav = $rootScope.hideNav = true; + $state.go('access_denied'); + } + }else{ + $scope.hideNav = $rootScope.hideNav = true; + } + }, + //error + function( error ){ + $scope.error = error.message; + console.log('ERROR: '+error.message); + throw new Error('Error: '+error.message); - // Show navbar if form is not public AND user is loggedin - if(!$scope.myform.isLive && $rootScope.authentication.isAuthenticated()){ - $rootScope.hideNav = false; - }else if(!$scope.myform.isLive){ - $state.go('access_denied'); - } - console.log('$rootScope.hideNav: '+$rootScope.hideNav); - console.log('$scope.form.isLive: '+$scope.myform.isLive); - }, - //error - function( error ){ - $scope.error = error.message; - console.log('ERROR: '+error.message); - $state.go('access_denied'); - }); + $state.go('access_denied'); + } + ); + }; } ]); diff --git a/public/dist/application.min.css b/public/dist/application.min.css index 5246f001..4624dc5a 100644 --- a/public/dist/application.min.css +++ b/public/dist/application.min.css @@ -1 +1 @@ -.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.content{margin-top:70px}.undecorated-link:hover{text-decoration:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.ng-invalid.ng-dirty{border-color:#FA787E}.ng-valid.ng-dirty{border-color:#78FA89}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{position:fixed;top:0;left:0;height:100%;width:100%;z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff;background-color:rgba(250,120,126,.65) #FA787E}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}.custom-select{position:relative;display:block;margin-top:.5em;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select option{font-weight:400}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}section.content p{word-break:break-all}.btn{border:1px solid #c6c6c6!important}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px;font-weight:400}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.admin-form .panel-heading a:hover{text-decoration:none}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.current-fields .tool-panel>.panel-default .panel-heading a:hover{text-decoration:none}.submissions-table .table-outer.row{margin:1.5em 0 2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 6em 7em}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form a.btn{font-size:.95em}.form-item.create-new.new-form input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new.new-form select{background-color:#fff;width:inherit;color:#000}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;background-color:#fff;border-radius:7px;width:100%;border:25px solid #fff}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file +.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.content{margin-top:70px}.undecorated-link:hover{text-decoration:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{position:fixed;top:0;left:0;height:100%;width:100%;z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff;background-color:rgba(250,120,126,.65) #FA787E}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select option{font-weight:400}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}section.content p{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px;font-weight:400}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.admin-form .panel-heading a:hover{text-decoration:none}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.current-fields .tool-panel>.panel-default .panel-heading a:hover{text-decoration:none}.submissions-table .table-outer.row{margin:1.5em 0 2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 6em 7em}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;background-color:#fff;border-radius:7px;width:100%;border:25px solid #fff}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 3e8b44c3..43439338 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1 +1,2 @@ -"use strict";var ApplicationConfiguration=function(){var applicationModuleName="medform",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||(event.preventDefault(),$state.go("home"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null===permissions||authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$state.go("access_denied")))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]}}).state("viewPublicForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/view-public-form.client.view.html",data:{hideNav:!0}})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){var deleteModal;$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){deleteModal=$modal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController"})},$scope.cancelDeleteModal=function(){deleteModal&&deleteModal.dismiss("cancel")},$scope.remove=function(form_id){if(deleteModal&&deleteModal.opened){deleteModal.close();var form={};form_id?form._id=form_id:(form=CurrentForm.getForm(),form||(form=$scope.myform)),$http["delete"]("/forms/"+form._id).success(function(data,status,headers){console.log("form deleted successfully"),form_id||$state.go("listForms",{},{reload:!0}),$scope.myforms.length>0&&($scope.myforms=_.filter($scope.myforms,function(myform){return myform._id!==form._id}))}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})["finally"](function(){})}},$scope.update=$rootScope.update=function(immediate,cb){var continueUpdate=!0;if(immediate&&(continueUpdate=!$rootScope.saveInProgress),continueUpdate){console.log("begin updating form");var err=null;immediate&&($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data,console.log(response.data)})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),console.log(response.data),err=response.data})["finally"](function(){console.log("finished updating"),immediate&&($rootScope.saveInProgress=!1),cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$rootScope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$rootScope.showCreateModal||($rootScope.showCreateModal=!0)},$scope.closeCreateModal=function(){$rootScope.showCreateModal&&($rootScope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicate=function(form,form_index){delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form duplicated"),$scope.myforms.splice(form_index,0,data)}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.createNew=function(){var form={};form.title=$scope.myform.name.$modelValue,form.language=$scope.myform.language.$modelValue,$rootScope.showCreateModal=!0,$scope.myform.$valid&&$scope.myform.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form created"),$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeFromList=function(deleted_form_id){console.log("Remove existing form"),$http["delete"]("/forms/"+deleted_form_id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.length>0&&($scope.myforms=_.filter($scope.myforms,function(myform){return myform._id!==deleted_form_id}))}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.myform=form,!$scope.myform.isLive&&$rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$scope.myform.isLive||$state.go("access_denied"),console.log("$rootScope.hideNav: "+$rootScope.hideNav),console.log("$scope.form.isLive: "+$scope.myform.isLive)},function(error){$scope.error=error.message,console.log("ERROR: "+error.message),$state.go("access_denied")})}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",controller:function($scope){},link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!1,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("changeFocus",function(){return{scope:{focusDownId:"@",focusUpId:"@"},link:function(scope,elem,attrs){scope.focusUp=function(){scope.$first||(console.log("focusUp"),elem[0].previousElementSibling.find("input").focus()),scope.apply()},scope.focusDown=function(){scope.$last||elem[0].nextElementSibling.focus(),scope.apply()},angular.element("#"+scope.focusDownId).bind("click",function(){scope.focusDown()}),angular.element("#"+scope.focusUpId).bind("click",function(){scope.focusUp()})}}}),angular.module("forms").directive("fieldIconDirective",function($http,$compile){return{template:'',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="./modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType?scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0}:"natural"===scope.field.fieldType&&(scope.field.fieldMatchValue="",scope.$watch("scope.field",function(newField,oldField){}));var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data),$compile(element.contents())(scope)})};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$last?scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})}):$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")})}}}}),angular.module("forms").directive("formDirective",["$http","$timeout","timeCounter","Auth","$filter","$rootScope",function($http,$timeout,timeCounter,Auth,$filter,$rootScope){return{templateUrl:"./modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{form:"="},controller:function($scope){angular.element(document).ready(function(){$scope.selected=null,timeCounter.startClock(),$rootScope.setActiveField=function(field_id){console.log("form field clicked: "+field_id),$scope.selected=field_id,console.log($scope.selected)},$scope.hideOverlay=function(){$scope.selected=null,console.log($scope.myForm)},$scope.submit=function(){var _timeElapsed=timeCounter.stopClock();$scope.form.timeElapsed=_timeElapsed,$scope.form.percentageComplete=$filter("formValidity")($scope.form)/$scope.form.visible_form_fields.length*100,console.log($scope.form.percentageComplete),$scope.authentication=Auth,$scope.submitPromise=$http.post("/forms/"+$scope.form._id,$scope.form).success(function(data,status,headers){console.log("form submitted successfully"),$scope.form.submitted=!0}).error(function(error){console.log(error),$scope.error=error.message})},$scope.exitStartPage=function(){$scope.form.startPage.showStart=!1},$scope.reloadForm=function(){timeCounter.stopClock(),timeCounter.startClock(),$scope.form.submitted=!1,$scope.form.form_fields=_.chain($scope.form.form_fields).map(function(field){return field.fieldValue="",field}).value()}})}}}]),angular.module("forms").directive("tableDirective",["$http","$timeout","Auth",function($http,$timeout,Auth){return{templateUrl:"./modules/forms/views/directiveViews/table/table.html",restrict:"E",scope:{rows:"=",extras:"="},controller:function($scope){$scope.toggleChecker=function(checked){for(var rows=$scope.gridOptions.$gridScope.renderedRows,allChecked=!0,r=0;ri;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +"use strict";var ApplicationConfiguration=function(){var applicationModuleName="medform",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]}}).state("viewPublicForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/view-public-form.client.view.html",data:{hideNav:!0}})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$modal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController"})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){err=response.data})["finally"](function(){updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb&&cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicate=function(form_index){var form=_.clone($scope.myforms[form_index]);form._id="",$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form duplicated"),$scope.myforms.splice(form_index+1,0,data),console.log($scope.myforms[3]._id)}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.createNew=function(){console.log($scope.forms.createForm);var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm){$scope.initForm=function(){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.myform=form,$scope.myform.isLive||($rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$state.go("access_denied"))},function(error){throw $scope.error=error.message,console.error("ERROR: "+error.message),new Error("Error: "+error.message)})}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",controller:function($scope){},link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("changeFocus",function(){return{scope:{focusDownId:"@",focusUpId:"@"},link:function(scope,elem,attrs){scope.focusUp=function(){scope.$first||(console.log("focusUp"),elem[0].previousElementSibling.find("input").focus()),scope.apply()},scope.focusDown=function(){scope.$last||elem[0].nextElementSibling.focus(),scope.apply()},angular.element("#"+scope.focusDownId).bind("click",function(){scope.focusDown()}),angular.element("#"+scope.focusUpId).bind("click",function(){scope.focusUp()})}}}),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:function($scope){$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages;var _current_upload=null;$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update;$scope.pdfFields;$scope.cancelUpload=function(){_current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(files){if(files&&files.length){var file=files[0];console.log(file),_current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),console.log($scope.myform.pdf),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","timeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:function($scope){$scope.addField={},$scope.addField.types=FormFields.fields,$scope.addField.types.forEach(function(type){return type.lastAddedID=1,type}),$scope.accordion={},$scope.accordion.oneAtATime=!0,$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},$scope.addNewField=function(addOrReturn,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1};return console.log("\n\n---------\nAdded field CLIENT"),console.log(newField),addOrReturn?void $scope.myform.form_fields.push(newField):newField},$scope.deleteField=function(hashKey){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].$$hashKey===hashKey){$scope.myform.form_fields.splice(i,1);break}},$scope.duplicateField=function(field_index){console.log("field_index: "+field_index);var field=$scope.addNewField(!1,$scope.myform.form_fields[field_index].fieldType);field.title=$scope.myform.form_fields[field_index].title,console.log($scope.myform.form_fields[field_index]),$scope.myform.form_fields.splice(field_index+1,0,field)},$scope.addButton=function(newButtons){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var hashKey=_.chain(button.$$hashKey).words().last().parseInt().value(),i=0;i<$scope.myform.startPage.buttons.length;i++){var currHashKey=_.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();if(currHashKey===hashKey){$scope.myform.startPage.buttons.splice(i,1);break}}},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="./modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType?scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0}:"natural"===scope.field.fieldType&&(scope.field.fieldMatchValue="",scope.$watch("scope.field",function(newField,oldField){}));var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data),$compile(element.contents())(scope)})};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$last?scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})}):$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")})}}}}),angular.module("forms").directive("submissionsFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/submissions-form.client.view.html",restrict:"E",scope:{myform:"=",user:"="},controller:function($scope){$scope.table={masterChecker:!1,rows:[]},$scope.isAtLeastOneChecked=function(){for(var i=0;i<$scope.table.rows.length;i++)if($scope.table.rows[i].selected)return!0;return!1},$scope.toggleAllCheckers=function(){for(var i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected=$scope.table.masterChecker},$scope.toggleObjSelection=function($event,description){$event.stopPropagation()},$scope.rowClicked=function(row_index){$scope.table.rows[row_index].selected=!$scope.table.rows[row_index].selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();$http({url:"/forms/"+$scope.myform._id+"/submissions",method:"DELETE",data:{deleted_submissions:delete_ids},headers:{"Content-Type":"application/json;charset=utf-8"}}).success(function(data,status,headers){for(var tmpArray=[],i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected||tmpArray.push($scope.table.rows[i]);console.log(tmpArray),$scope.table.rows=tmpArray}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$scope.exportSubmissions=function(type){var fileMIMETypeMap={xls:"vnd.openxmlformats-officedocument.spreadsheetml.sheet",json:"json",csv:"csv"},blob=new Blob([document.getElementById("table-submission-data").innerHTM],{type:"application/"+fileMIMETypeMap[type]+";charset=utf-8"});saveAs(blob,$scope.myform.title+"_sumbissions_export_"+Date.now()+"."+type)},$scope.showSubmissions=function(){$http.get("/forms/"+$scope.myform._id+"/submissions").success(function(data,status,headers){for(var _tmpSubFormFields,_data=[],defaultFormFields=JSON.parse(JSON.stringify($scope.myform.form_fields)),i=0;ii;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/forms/controllers/submit-form.client.controller.js b/public/modules/forms/controllers/submit-form.client.controller.js index 92b0b5b6..20ee9abc 100644 --- a/public/modules/forms/controllers/submit-form.client.controller.js +++ b/public/modules/forms/controllers/submit-form.client.controller.js @@ -1,32 +1,40 @@ 'use strict'; // Forms controller -angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', - function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm) { +angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', 'Auth', + function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm, Auth) { + $scope.authentication = Auth; + $scope.initForm = function(){ + Forms.get({ + formId: $stateParams.formId + }).$promise.then( + //success + function(form){ + $scope.myform = form; - Forms.get({ - formId: $stateParams.formId - }).$promise.then( - //success - function(form){ - $scope.myform = form; - - // Show navbar if form is not public AND user is loggedin - if(!$scope.myform.isLive && $rootScope.authentication.isAuthenticated()){ - $rootScope.hideNav = false; - }else if(!$scope.myform.isLive){ - $state.go('access_denied'); - } - console.log('$rootScope.hideNav: '+$rootScope.hideNav); - console.log('$scope.form.isLive: '+$scope.myform.isLive); - }, - //error - function( error ){ - $scope.error = error.message; - console.log('ERROR: '+error.message); - $state.go('access_denied'); - }); + if(!$scope.myform.isLive){ + // Show navbar if form is not public AND user IS loggedin + if($scope.authentication.isAuthenticated()){ + $scope.hideNav = $rootScope.hideNav = false; + } + // Redirect if form is not public user IS NOT loggedin + else { + $scope.hideNav = $rootScope.hideNav = true; + $state.go('access_denied'); + } + }else{ + $scope.hideNav = $rootScope.hideNav = true; + } + }, + //error + function( error ){ + $scope.error = error.message; + console.error('ERROR: '+error.message); + $state.go('access_denied'); + } + ); + }; } ]); \ No newline at end of file diff --git a/public/modules/forms/directives/auto-save.client.directive.js b/public/modules/forms/directives/auto-save.client.directive.js index 7bd69c65..7d61fe2c 100644 --- a/public/modules/forms/directives/auto-save.client.directive.js +++ b/public/modules/forms/directives/auto-save.client.directive.js @@ -5,9 +5,6 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun return { require: ['^form'], restrict: 'AE', - controller: function ($scope) { - - }, link: function($scope, $element, $attrs, $ctrls) { angular.element(document).ready(function() { diff --git a/public/modules/forms/directives/change-focus.client.directive.js b/public/modules/forms/directives/change-focus.client.directive.js deleted file mode 100644 index ce86fabc..00000000 --- a/public/modules/forms/directives/change-focus.client.directive.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -angular.module('forms').directive('changeFocus', function() { - return { - scope:{ - focusDownId: '@', - focusUpId: '@', - }, - link: function(scope, elem, attrs) { - // console.log('aoeuaoeuaoeuaou'); - scope.focusUp = function(){ - if(!scope.$first) { - console.log('focusUp'); - elem[0].previousElementSibling.find('input').focus(); - } - scope.apply(); - }; - scope.focusDown = function(){ - if(!scope.$last) { - elem[0].nextElementSibling.focus(); - } - scope.apply(); - }; - - //Bind 'focus-down' click event to given dom element - angular.element('#' + scope.focusDownId).bind('click', function() { - scope.focusDown(); - }); - - //Bind 'focus-up' click event to given dom element - angular.element('#' + scope.focusUpId).bind('click', function() { - scope.focusUp(); - }); - } - }; -}); \ No newline at end of file diff --git a/public/modules/forms/directives/configure-form.client.directive.js b/public/modules/forms/directives/configure-form.client.directive.js index 22d54b04..cd67d622 100644 --- a/public/modules/forms/directives/configure-form.client.directive.js +++ b/public/modules/forms/directives/configure-form.client.directive.js @@ -1,9 +1,9 @@ 'use strict'; -angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields', - function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) { +angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'TimeCounter', 'Auth', 'FormFields', + function ($rootScope, $http, Upload, $timeout, TimeCounter, Auth, FormFields) { return { - templateUrl: './modules/forms/views/directiveViews/form/configure-form.client.view.html', + templateUrl: 'modules/forms/views/directiveViews/form/configure-form.client.view.html', restrict: 'E', scope: { myform:'=', @@ -16,20 +16,20 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt $scope.pdfLoading = false; $scope.languages = $rootScope.languages; - var _current_upload = null; + this._current_upload = null; $scope.resetForm = $rootScope.resetForm; $scope.update = $rootScope.update; - var _unbindedPdfFields = $scope.pdfFields; + this._unbindedPdfFields = $scope.pdfFields; //DAVID: TODO: finish this so we can create a Form.pdfFieldMap // $scope.getUnbindedPdfFields = function(fieldType){ - // _unbindedPdfFields = $scope.pdfFields + // this._unbindedPdfFields = $scope.pdfFields // } //PDF Functions $scope.cancelUpload = function(){ - _current_upload.abort(); + this._current_upload.abort(); $scope.pdfLoading = false; $scope.removePDF(); }; @@ -43,13 +43,14 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt }; $scope.uploadPDF = function(files) { + console.log(files) if (files && files.length) { // for (var i = 0; i < files.length; i++) { var file = files[0]; console.log(file); - _current_upload = Upload.upload({ + this._current_upload = Upload.upload({ url: '/upload/pdf', fields: { 'user': $scope.user, @@ -60,6 +61,7 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); $scope.log = 'progress: ' + progressPercentage + '% ' + evt.config.file.name + '\n' + $scope.log; + $scope.pdfLoading = true; }).success(function (data, status, headers, config) { $scope.log = 'file ' + data.originalname + ' uploaded as '+ data.name +'. JSON: ' + JSON.stringify(data) + '\n' + $scope.log; diff --git a/public/modules/forms/directives/edit-form.client.directive.js b/public/modules/forms/directives/edit-form.client.directive.js index 5d114710..1473b618 100644 --- a/public/modules/forms/directives/edit-form.client.directive.js +++ b/public/modules/forms/directives/edit-form.client.directive.js @@ -1,15 +1,13 @@ 'use strict'; -angular.module('forms') -.directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields', - function ($rootScope, $q, $http, $timeout, timeCounter, Auth, FormFields) { +angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'TimeCounter', 'Auth', 'FormFields', + function ($rootScope, $q, $http, $timeout, TimeCounter, Auth, FormFields) { return { templateUrl: './modules/forms/views/directiveViews/form/edit-form.client.view.html', restrict: 'E', scope: { myform:'=', }, - // transclude: true, controller: function($scope){ /* @@ -17,7 +15,7 @@ angular.module('forms') */ //Populate AddField with all available form field types $scope.addField = {}; - $scope.addField.types = FormFields.fields; + $scope.addField.types = FormFields.types; $scope.addField.types.forEach(function(type){ type.lastAddedID = 1; @@ -76,7 +74,7 @@ angular.module('forms') // // console.log('has class .dropzone :'+); // // if ($(e.target).hasClass('dropzone') && ui.item.sortable.droptarget && e.target != ui.item.sortable.droptarget[0] ) { // // // restore original types - // // $scope.addField.types = FormFields.fields; + // // $scope.addField.types = FormFields.types; // // } @@ -88,7 +86,7 @@ angular.module('forms') ** Field CRUD Methods */ // Add a new field - $scope.addNewField = function(addOrReturn, fieldType){ + $scope.addNewField = function(modifyForm, fieldType){ // incr field_id counter $scope.addField.lastAddedID++; @@ -104,25 +102,21 @@ angular.module('forms') } } var newField = { - 'title' : fieldTitle, - 'fieldType' : fieldType, - 'fieldValue' : '', - 'required' : true, - 'disabled' : false, + title: fieldTitle, + fieldType: fieldType, + fieldValue: '', + required: true, + disabled: false, + deletePreserved: false }; console.log('\n\n---------\nAdded field CLIENT'); console.log(newField); // put newField into fields array - if(addOrReturn){ + if(modifyForm){ $scope.myform.form_fields.push(newField); - }else { - return newField; } - - - // console.log(Date.now()); - // console.log($scope.myform.form_fields.length); + return newField; }; // deletes particular field on button click @@ -144,7 +138,6 @@ angular.module('forms') //Insert field at selected index $scope.myform.form_fields.splice(field_index+1, 0, field); - }; @@ -168,7 +161,7 @@ angular.module('forms') var hashKey = _.chain(button.$$hashKey).words().last().parseInt().value(); for(var i = 0; i < $scope.myform.startPage.buttons.length; i++){ - var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();; + var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value(); if(currHashKey === hashKey){ $scope.myform.startPage.buttons.splice(i, 1); diff --git a/public/modules/forms/directives/submissions-form.client.directive.js b/public/modules/forms/directives/edit-submissions-form.client.directive.js similarity index 96% rename from public/modules/forms/directives/submissions-form.client.directive.js rename to public/modules/forms/directives/edit-submissions-form.client.directive.js index 3ac82c74..b210cb81 100644 --- a/public/modules/forms/directives/submissions-form.client.directive.js +++ b/public/modules/forms/directives/edit-submissions-form.client.directive.js @@ -1,9 +1,9 @@ 'use strict'; -angular.module('forms').directive('submissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields', - function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) { +angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'TimeCounter', 'Auth', 'FormFields', + function ($rootScope, $http, Upload, $timeout, TimeCounter, Auth, FormFields) { return { - templateUrl: './modules/forms/views/directiveViews/form/submissions-form.client.view.html', + templateUrl: './modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html', restrict: 'E', scope: { myform:'=', diff --git a/public/modules/forms/directives/on-finish-render.client.directive.js b/public/modules/forms/directives/on-finish-render.client.directive.js index 434c1654..01060462 100644 --- a/public/modules/forms/directives/on-finish-render.client.directive.js +++ b/public/modules/forms/directives/on-finish-render.client.directive.js @@ -5,6 +5,8 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo restrict: 'A', link: function (scope, element, attrs) { + // $rootScope.$broadcast(' Started'); + //Don't do anything if we don't have a ng-repeat on the current element if(!element.attr('ng-repeat')){ return; @@ -12,17 +14,19 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; - if(!scope.$last) { - $timeout(function () { - // console.log(broadcastMessage+'Started'); - $rootScope.$broadcast(broadcastMessage+'Started'); + if(scope.$first) { + scope.$evalAsync(function () { + // console.log(broadcastMessage+' Started'); + // console.log(Date.now()); + $rootScope.$broadcast(broadcastMessage+' Started'); }); }else if(scope.$last) { - $timeout(function () { - element.ready(function () { + scope.$evalAsync(function () { + // element.ready(function () { // console.log(broadcastMessage+'Finished'); - $rootScope.$broadcast(broadcastMessage+'Finished'); - }); + // console.log(Date.now()); + $rootScope.$broadcast(broadcastMessage+' Finished'); + // }); }); } } diff --git a/public/modules/forms/directives/submit-form.client.directive.js b/public/modules/forms/directives/submit-form.client.directive.js index 98ef6464..4e690b1f 100644 --- a/public/modules/forms/directives/submit-form.client.directive.js +++ b/public/modules/forms/directives/submit-form.client.directive.js @@ -1,7 +1,7 @@ 'use strict'; -angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', '$filter', '$rootScope', - function ($http, $timeout, timeCounter, Auth, $filter, $rootScope) { +angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope', + function ($http, $timeout, TimeCounter, Auth, $filter, $rootScope) { return { templateUrl: './modules/forms/views/directiveViews/form/submit-form.client.view.html', restrict: 'E', @@ -12,7 +12,7 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo angular.element(document).ready(function() { $scope.selected = null; - timeCounter.startClock() + TimeCounter.startClock() $rootScope.setActiveField = function (field_id) { console.log('form field clicked: '+field_id); @@ -25,7 +25,7 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo }; $scope.submit = function(){ - var _timeElapsed = timeCounter.stopClock(); + var _timeElapsed = TimeCounter.stopClock(); $scope.form.timeElapsed = _timeElapsed; // console.log('percentageComplete: '+$filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100+'%'); @@ -53,8 +53,8 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo }; $scope.reloadForm = function(){ - timeCounter.stopClock(); - timeCounter.startClock(); + TimeCounter.stopClock(); + TimeCounter.startClock(); $scope.form.submitted = false; $scope.form.form_fields = _.chain($scope.form.form_fields).map(function(field){ field.fieldValue = ''; diff --git a/public/modules/forms/directives/table.client.directive.js b/public/modules/forms/directives/table.client.directive.js deleted file mode 100644 index b327da68..00000000 --- a/public/modules/forms/directives/table.client.directive.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -angular.module('forms').directive('tableDirective', ['$http', '$timeout', 'Auth', - function ($http, $timeout, Auth) { - return { - templateUrl: './modules/forms/views/directiveViews/table/table.html', - restrict: 'E', - scope: { - rows:'=', - extras:'=', - }, - controller: function($scope){ - - $scope.toggleChecker = function(checked) { - var rows = $scope.gridOptions.$gridScope.renderedRows, - allChecked = true; - - for (var r = 0; r < rows.length; r++) { - if (rows[r].entity.checker !== true) { - allChecked = false; - break; - } - } - - $scope.gridOptions.$gridScope.checker = allChecked; - }; - - - - }, - - }; - } -]); \ No newline at end of file diff --git a/public/modules/forms/services/form-fields.client.service.js b/public/modules/forms/services/form-fields.client.service.js index 2012c95c..cef5e2a7 100644 --- a/public/modules/forms/services/form-fields.client.service.js +++ b/public/modules/forms/services/form-fields.client.service.js @@ -2,7 +2,7 @@ angular.module('forms').service('FormFields', [ function() { - this.fields = [ + this.types = [ { name : 'textfield', value : 'Short Text' diff --git a/public/modules/forms/services/time-counter.client.service.js b/public/modules/forms/services/time-counter.client.service.js index fdd2e894..e0131223 100644 --- a/public/modules/forms/services/time-counter.client.service.js +++ b/public/modules/forms/services/time-counter.client.service.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('forms').service('timeCounter', [ +angular.module('forms').service('TimeCounter', [ function(){ var _startTime, _endTime, that=this; diff --git a/public/modules/forms/tests/admin-from.client.controller.test.js b/public/modules/forms/tests/admin-form.client.controller.test.js similarity index 87% rename from public/modules/forms/tests/admin-from.client.controller.test.js rename to public/modules/forms/tests/admin-form.client.controller.test.js index dda89056..695f7cdc 100644 --- a/public/modules/forms/tests/admin-from.client.controller.test.js +++ b/public/modules/forms/tests/admin-form.client.controller.test.js @@ -2,7 +2,7 @@ (function() { // Forms Controller Spec - describe('AdminFormController Tests', function() { + describe('AdminForm Controller Tests', function() { // Initialize global variables var AdminFormController, createAdminFormController, @@ -28,9 +28,9 @@ admin: 'ed873933b1f1dea0ce12fab9', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '525a8422f6d0f87f0e407a33' }; @@ -40,14 +40,14 @@ admin: 'ed873933b1f1dea0ce12fab9', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], visible_form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '525a8422f6d0f87f0e407a33' }; @@ -70,7 +70,7 @@ this.opened = false; this.cancelCallback( type ); }; - } + }; @@ -93,6 +93,12 @@ }); }); + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(module('stateMock')); + //Mock Users Service beforeEach(module(function($provide) { $provide.service('User', function($q) { @@ -148,10 +154,6 @@ }); })); - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); - - beforeEach(module('stateMock')); beforeEach(inject(function($modal) { spyOn($modal, 'open').and.returnValue(new fakeModal()); @@ -224,14 +226,15 @@ scope.openDeleteModal(); scope.deleteModal.result(function(selectedItem){ - scope.selected = selectedItem; + this.selected = selectedItem; }, function(type){ - $scope.canceled = true; + this.canceled = true; }); scope.removeCurrentForm(); $httpBackend.flush(); + $state.ensureAllTransitionsHappened(); }); it('$scope.update() should send a PUT request with the id of form', function() { @@ -267,8 +270,8 @@ this.canceled = true; }); + //Run controller functionality scope.cancelDeleteModal(); - console.log(scope.deleteModal.opened); expect( scope.deleteModal.opened ).toEqual(false); expect( scope.deleteModal.canceled ).toEqual(true); diff --git a/public/modules/forms/tests/directives/configure-form.client.directive.test.js b/public/modules/forms/tests/directives/configure-form.client.directive.test.js new file mode 100644 index 00000000..1195044a --- /dev/null +++ b/public/modules/forms/tests/directives/configure-form.client.directive.test.js @@ -0,0 +1,137 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('configureForm Tests', function() { + // Initialize global variables + var el, scope, controller, $httpBackend; + + var sampleUser = { + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local', + roles: ['user'], + _id: 'ed873933b1f1dea0ce12fab9', + }; + + var pdfObj = { + fieldname:"file", + originalname:"test.pdf", + name:"1440112660375.pdf", + encoding:"7bit", + mimetype:"application/pdf", + path:"uploads/tmp/test@test.com/1440112660375.pdf", + extension:"pdf", + size:56223, + truncated:false, + buffer:null + }; + + var sampleForm = { + title: 'Form Title', + admin: 'ed873933b1f1dea0ce12fab9', + language: 'english', + form_fields: [ + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} + ], + pdf: {}, + pdfFieldMap: {}, + startPage: { + showStart: false + }, + hideFooter: false, + isGenerated: false, + isLive: false, + autofillPDFs: false, + _id: '525a8422f6d0f87f0e407a33', + }; + + // The $resource service augments the response object with methods for updating and deleting the resource. + // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match + // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. + // When the toEqualData matcher compares two objects, it takes only object properties into + // account and ignores methods. + beforeEach(function() { + jasmine.addMatchers({ + toEqualData: function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { + pass: angular.equals(actual, expected) + }; + } + }; + } + }); + }); + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + beforeEach(module('stateMock')); + beforeEach(module('module-templates')); + + beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) { + //Instantiate directive. + var tmp_scope = $rootScope.$new(); + tmp_scope.myform = sampleForm; + tmp_scope.user = sampleUser; + + //gotacha: Controller and link functions will execute. + el = angular.element(''); + $compile(el)(tmp_scope); + $rootScope.$digest(); + + // Point global variables to injected services + $httpBackend = _$httpBackend_; + + // $httpBackend.whenGET(/.+\.html$/).respond(''); + $httpBackend.whenGET('/users/me/').respond(''); + + //Grab controller instance + controller = el.controller(); + + //Grab scope. Depends on type of scope. + //See angular.element documentation. + scope = el.isolateScope() || el.scope(); + + // spyOn(scope, 'update'); + // spyOn(scope, 'resetForm'); + })); + + it('$scope.uploadPDF() should upload a pdf file', function() { + // expect(scope.isInitialized).toBeDefined() + // expect(scope.log).toEqual(''); + + expect(scope.pdfLoading).toBe(false); + + //Set POST response + $httpBackend.when('POST', '/upload/pdf').respond(pdfObj); + + var files = [{}]; + scope.uploadPDF(files); + + $httpBackend.flush(); + expect(scope.myform.pdf).toEqualData(pdfObj); + }); + + it('$scope.removePDF() should removed uploaded pdf file', function() { + // expect(scope.isInitialized).toBeDefined() + // expect(scope.log).toEqual(''); + + scope.myform.pdf = pdfObj; + scope.myform.isGenerated = true; + scope.myform.autofillPDFs = true; + + scope.removePDF(); + + expect(scope.myform.pdf).toEqual(null); + expect(scope.myform.isGenerated).toBe(false); + expect(scope.myform.autofillPDFs).toBe(false); + }); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/directives/edit-form.client.directive.test.js b/public/modules/forms/tests/directives/edit-form.client.directive.test.js new file mode 100644 index 00000000..23bf2cb6 --- /dev/null +++ b/public/modules/forms/tests/directives/edit-form.client.directive.test.js @@ -0,0 +1,126 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('editForm Tests', function() { + // Initialize global variables + var el, scope, controller, $httpBackend; + + var sampleUser = { + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local', + roles: ['user'], + _id: 'ed873933b1f1dea0ce12fab9', + }; + + var pdfObj = { + fieldname:"file", + originalname:"test.pdf", + name:"1440112660375.pdf", + encoding:"7bit", + mimetype:"application/pdf", + path:"uploads/tmp/test@test.com/1440112660375.pdf", + extension:"pdf", + size:56223, + truncated:false, + buffer:null + }; + + var sampleForm = { + title: 'Form Title', + admin: 'ed873933b1f1dea0ce12fab9', + language: 'english', + form_fields: [ + {fieldType:'textfield', title:'First Name', fieldValue: '', required: true, disabled: false, deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', required: true, disabled: false, deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', required: true, disabled: false, deletePreserved: false} + ], + pdf: {}, + pdfFieldMap: {}, + startPage: { + showStart: false + }, + hideFooter: false, + isGenerated: false, + isLive: false, + autofillPDFs: false, + _id: '525a8422f6d0f87f0e407a33', + }; + + // The $resource service augments the response object with methods for updating and deleting the resource. + // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match + // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. + // When the toEqualData matcher compares two objects, it takes only object properties into + // account and ignores methods. + beforeEach(function() { + jasmine.addMatchers({ + toEqualData: function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { + pass: angular.equals(actual, expected) + }; + } + }; + } + }); + }); + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + beforeEach(module('stateMock')); + beforeEach(module('module-templates')); + + beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) { + //Instantiate directive. + var tmp_scope = $rootScope.$new(); + tmp_scope.myform = sampleForm; + + //gotacha: Controller and link functions will execute. + el = angular.element(''); + $compile(el)(tmp_scope); + $rootScope.$digest(); + + // Point global variables to injected services + $httpBackend = _$httpBackend_; + + // $httpBackend.whenGET(/.+\.html$/).respond(''); + $httpBackend.whenGET('/users/me/').respond(''); + + //Grab controller instance + controller = el.controller(); + + //Grab scope. Depends on type of scope. + //See angular.element documentation. + scope = el.isolateScope() || el.scope(); + + })); + + it('$scope.addNewField() should ADD a new field to $scope.myform.form_fields', function() { + scope.addNewField(true, 'textfield'); + + var sampleFormField = { + fieldType:'checkbox', + title:'hockey', + fieldValue: '', + required: true, + disabled: false, + deletePreserved: false + }; + + expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1); + expect(_.last(scope.myform.form_fields)).toEqualData(sampleFormField); + }); + + it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() { + scope.deleteField(scope.myform.form_fields[0].$$hashKey); + + expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length-1); + expect(_.first(scope.myform.form_fields)).toEqualData(sampleForm.form_fields[1]); + }); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/directives/field-icon.client.directive.test.js b/public/modules/forms/tests/directives/field-icon.client.directive.test.js new file mode 100644 index 00000000..39e5656b --- /dev/null +++ b/public/modules/forms/tests/directives/field-icon.client.directive.test.js @@ -0,0 +1,54 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('FieldIcon Directive Tests', function() { + // Initialize global variables + var scope, + FormFields, + faClasses = { + 'textfield': 'fa fa-pencil-square-o', + 'dropdown': 'fa fa-th-list', + 'date': 'fa fa-calendar', + 'checkbox': 'fa fa-check-square-o', + 'radio': 'fa fa-dot-circle-o', + 'email': 'fa fa-envelope-o', + 'textarea': 'fa fa-pencil-square', + 'legal': 'fa fa-legal', + 'file': 'fa fa-cloud-upload', + 'rating': 'fa fa-star-half-o', + 'link': 'fa fa-link', + 'scale': 'fa fa-sliders', + 'stripe': 'fa fa-credit-card', + 'statement': 'fa fa-quote-left', + 'yes_no': 'fa fa-toggle-on', + 'number': 'fa fa-slack' + }; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function ($rootScope, _FormFields_) { + scope = $rootScope.$new(); + FormFields = _FormFields_; + })); + + it('should be able render all field-icon types', inject(function($compile) { + var currType, + currClass; + for(var i=0; i')(scope); + scope.$digest(); + + expect(currClass).toBeDefined(); + + expect(element.find('i')).not.toBe(null); + expect(element.find('i').hasClass(currClass)).toBe(true); + } + + })); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/directives/on-finish-render.client.directive.test.js b/public/modules/forms/tests/directives/on-finish-render.client.directive.test.js new file mode 100644 index 00000000..a6f0390d --- /dev/null +++ b/public/modules/forms/tests/directives/on-finish-render.client.directive.test.js @@ -0,0 +1,47 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('onFinishRender Directive Tests', function() { + // Initialize global variables + var scope, + FormFields; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function ($rootScope, _FormFields_) { + scope = $rootScope.$new(); + FormFields = _FormFields_; + spyOn($rootScope, '$broadcast'); + + })); + + it('should emit Custom "Finished" and "Started" events on ng-repeat', inject(function($compile, $rootScope) { + + // console.log(FormFields.types); + scope.myfields = FormFields.types; + + var e = $compile('
{{item.name}}
')(scope); + scope.$digest(); + + //run code to test + expect($rootScope.$broadcast).toHaveBeenCalledWith('editFormFields Started'); + expect(scope.$broadcast).toHaveBeenCalledWith('editFormFields Finished'); + })); + + it('should emit "ngRepeat Finished" and "ngRepeat Started" events on ng-repeat when attr is not set to string', inject(function($compile, $rootScope) { + + // console.log(FormFields.types); + scope.myfields = FormFields.types; + + var e = $compile('
{{item.name}}
')(scope); + scope.$digest(); + + //run code to test + expect($rootScope.$broadcast).toHaveBeenCalledWith('ngRepeat Started'); + expect(scope.$broadcast).toHaveBeenCalledWith('ngRepeat Finished'); + })); + + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/directives/submissions-form.client.directive.test.js b/public/modules/forms/tests/directives/submissions-form.client.directive.test.js deleted file mode 100644 index d1447461..00000000 --- a/public/modules/forms/tests/directives/submissions-form.client.directive.test.js +++ /dev/null @@ -1,91 +0,0 @@ -// 'use strict'; - -// (function() { -// // Forms Controller Spec -// describe('SubmissionsFormDirective Tests', function() { -// // Initialize global variables -// var SubmissionsFormDirective, -// scope, -// $httpBackend, -// $stateParams, -// $location; - -// // The $resource service augments the response object with methods for updating and deleting the resource. -// // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match -// // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. -// // When the toEqualData matcher compares two objects, it takes only object properties into -// // account and ignores methods. -// beforeEach(function() { -// jasmine.addMatchers({ -// toEqualData: function(util, customEqualityTesters) { -// return { -// compare: function(actual, expected) { -// return { -// pass: angular.equals(actual, expected) -// }; -// } -// }; -// } -// }); -// }); - -// // Then we can start by loading the main application module -// beforeEach(module(ApplicationConfiguration.applicationModuleName)); - -// // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). -// // This allows us to inject a service but then attach it to a variable -// // with the same name as the service. -// beforeEach(inject(function($controller, $rootScope, _$location_, _$stateParams_, _$httpBackend_) { -// // Set a new global scope -// scope = $rootScope.$new(); - -// // Point global variables to injected services -// $stateParams = _$stateParams_; -// $httpBackend = _$httpBackend_; -// $location = _$location_; - -// // Initialize the Forms controller. -// FormsController = $controller('AdminFormsController', { -// $scope: scope -// }); -// })); - -// function compileDirective(tpl) { -// // function to compile a fresh directive with the given template, or a default one -// // compile the tpl with the $rootScope created above -// // wrap our directive inside a form to be able to test -// // that our form integration works well (via ngModelController) -// // our directive instance is then put in the global 'elm' variable for further tests -// if (!tpl) tpl = '
'; -// tpl = '
' + tpl + ''; -// // inject allows you to use AngularJS dependency injection -// // to retrieve and use other services -// inject(function($compile) { -// var form = $compile(tpl)(scope); -// elm = form.find('div'); -// }); -// // $digest is necessary to finalize the directive generation -// scope.$digest(); -// } - -// describe('initialisation', function() { -// // before each test in this block, generates a fresh directive -// beforeEach(function() { -// compileDirective(); -// }); -// // a single test example, check the produced DOM -// it('should produce 2 buttons and a div', function() { -// expect(elm.find('button').length).toEqual(2); -// expect(elm.find('div').length).toEqual(1); -// }); -// it('should check validity on init', function() { -// expect(scope.form.$valid).toBeTruthy(); -// }); -// }); - -// it('$scope.find() should create an array with at least one article object fetched from XHR', inject(function(Forms) { - -// })); - -// }); -// }()); \ No newline at end of file diff --git a/public/modules/forms/tests/list-forms.client.controller.test.js b/public/modules/forms/tests/list-forms.client.controller.test.js index 769d9e75..c936881c 100644 --- a/public/modules/forms/tests/list-forms.client.controller.test.js +++ b/public/modules/forms/tests/list-forms.client.controller.test.js @@ -2,7 +2,7 @@ (function() { // Forms Controller Spec - describe('ListFormsController Tests', function() { + describe('ListForms Controller Tests', function() { // Initialize global variables var ListFormsController, createListFormsController, @@ -12,25 +12,14 @@ $location, $state; - var sampleUser = { - firstName: 'Full', - lastName: 'Name', - email: 'test@test.com', - username: 'test@test.com', - password: 'password', - provider: 'local', - roles: ['user'], - _id: 'ed873933b1f1dea0ce12fab9' - }; - var sampleForm = { title: 'Form Title', admin: 'ed873933b1f1dea0ce12fab9', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '525a8422f6d0f87f0e407a33' }; @@ -40,9 +29,9 @@ admin: 'ed873933b1f1dea0ce12fab9', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '525a8422f6d0f87f0e407a33' },{ @@ -50,9 +39,9 @@ admin: '39223933b1f1dea0ce12fab9', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '52f6d0f87f5a407a384220e3' },{ @@ -60,9 +49,9 @@ admin: '2fab9ed873937f0e1dea0ce1', language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false}, + {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false} ], _id: '922f6d0f87fed8730e4e1233' } @@ -87,62 +76,7 @@ } }); }); - - //Mock Users Service - beforeEach(module(function($provide) { - $provide.service('User', function($q) { - return { - getCurrent: function() { - var deferred = $q.defer(); - deferred.resolve( JSON.stringify(sampleUser) ); - return deferred.promise; - }, - login: function(credentials) { - var deferred = $q.defer(); - if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ - deferred.resolve( JSON.stringify(sampleUser) ); - }else { - deferred.resolve('Error: User could not be loggedin'); - } - - return deferred.promise; - }, - logout: function() { - var deferred = $q.defer(); - deferred.resolve(null); - return deferred.promise; - }, - signup: function(credentials) { - var deferred = $q.defer(); - if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ - deferred.resolve( JSON.stringify(sampleUser) ); - }else { - deferred.resolve('Error: User could not be signed up'); - } - - return deferred.promise; - } - }; - }); - })); - - //Mock Authentication Service - beforeEach(module(function($provide) { - $provide.service('Auth', function() { - return { - ensureHasCurrentUser: function() { - return sampleUser; - }, - isAuthenticated: function() { - return true; - }, - getUserState: function() { - return true; - } - }; - }); - })); - + // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); @@ -264,7 +198,7 @@ }, $dirty: true, $valid: true, - } + }; // scope.forms.createForm.language.$modelValue = 'english'; // scope.forms.createForm.name.$modelValue = 'Test Form5'; // scope.forms.createForm.$dirty = true; @@ -279,6 +213,7 @@ scope.createNew(); $httpBackend.flush(); + $state.ensureAllTransitionsHappened(); })); }); diff --git a/public/modules/forms/tests/services/current-form.client.service.test.js b/public/modules/forms/tests/services/current-form.client.service.test.js new file mode 100644 index 00000000..63c5717b --- /dev/null +++ b/public/modules/forms/tests/services/current-form.client.service.test.js @@ -0,0 +1,54 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('CurrentForm Service Tests', function() { + // Initialize global variables + var CurrentForm, + sampleForm = { + title: 'Form Title', + admin: 'ed873933b1f1dea0ce12fab9', + language: 'english', + form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + ], + _id: '525a8422f6d0f87f0e407a33' + }; + + + // The $resource service augments the response object with methods for updating and deleting the resource. + // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match + // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. + // When the toEqualData matcher compares two objects, it takes only object properties into + // account and ignores methods. + beforeEach(function() { + jasmine.addMatchers({ + toEqualData: function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { + pass: angular.equals(actual, expected) + }; + } + }; + } + }); + }); + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function (_CurrentForm_) { + CurrentForm = _CurrentForm_; + })); + + + it('CurrentForm be able to get() and set() a Form', function() { + CurrentForm.setForm(sampleForm); + var newForm = CurrentForm.getForm(); + expect(sampleForm).toEqualData(newForm); + }); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/services/time-counter.client.service.test.js b/public/modules/forms/tests/services/time-counter.client.service.test.js new file mode 100644 index 00000000..641bd83b --- /dev/null +++ b/public/modules/forms/tests/services/time-counter.client.service.test.js @@ -0,0 +1,28 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('TimeCounter Service Tests', function() { + // Initialize global variables + var TimeCounter; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(inject(function (_TimeCounter_) { + TimeCounter = _TimeCounter_; + })); + + + it('should be able to time 1 second interval as 1 second', function() { + var timeSpent = 0; + TimeCounter.startClock(); + + setTimeout(function(){ + timeSpent = TimeCounter.stopClock(); + expect(timeSpent).toEqual(1); + },1000); + + }); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/tests/submit-form.client.controller.test.js b/public/modules/forms/tests/submit-form.client.controller.test.js new file mode 100644 index 00000000..bc5b80f0 --- /dev/null +++ b/public/modules/forms/tests/submit-form.client.controller.test.js @@ -0,0 +1,228 @@ +'use strict'; + +(function() { + // Forms Controller Spec + describe('SubmitForm Controller Tests', function() { + // Initialize global variables + var SubmitFormController, + createSubmitFormController, + scope, + $httpBackend, + $stateParams, + $location, + $state; + + var sampleUser = { + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local', + roles: ['user'], + _id: 'ed873933b1f1dea0ce12fab9' + }; + + var sampleForm = { + title: 'Form Title', + admin: 'ed873933b1f1dea0ce12fab9', + language: 'english', + form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + ], + isLive: false, + _id: '525a8422f6d0f87f0e407a33', + visible_form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false} + ], + }; + + //Mock Users Service + beforeEach(module(function($provide) { + $provide.service('User', function($q) { + return { + getCurrent: function() { + var deferred = $q.defer(); + deferred.resolve( JSON.stringify(sampleUser) ); + return deferred.promise; + }, + login: function(credentials) { + var deferred = $q.defer(); + if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ + deferred.resolve( JSON.stringify(sampleUser) ); + }else { + deferred.resolve('Error: User could not be loggedin'); + } + + return deferred.promise; + }, + logout: function() { + var deferred = $q.defer(); + deferred.resolve(null); + return deferred.promise; + }, + signup: function(credentials) { + var deferred = $q.defer(); + if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ + deferred.resolve( JSON.stringify(sampleUser) ); + }else { + deferred.resolve('Error: User could not be signed up'); + } + + return deferred.promise; + } + }; + }); + })); + + //Mock Authentication Service + beforeEach(module(function($provide) { + $provide.service('Auth', function() { + return { + ensureHasCurrentUser: function() { + return sampleUser; + }, + isAuthenticated: function() { + return true; + }, + getUserState: function() { + return true; + } + }; + }); + })); + + + + // The $resource service augments the response object with methods for updating and deleting the resource. + // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match + // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. + // When the toEqualData matcher compares two objects, it takes only object properties into + // account and ignores methods. + beforeEach(function() { + jasmine.addMatchers({ + toEqualData: function(util, customEqualityTesters) { + return { + compare: function(actual, expected) { + return { + pass: angular.equals(actual, expected) + }; + } + }; + } + }); + }); + + + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + beforeEach(module('stateMock')); + + //Mock Authentication Service + beforeEach(module(function($provide) { + $provide.service('Auth', function() { + return { + ensureHasCurrentUser: function() { + return sampleUser; + }, + isAuthenticated: function() { + return true; + }, + getUserState: function() { + return true; + } + }; + }); + })); + + //Mock Users Service + beforeEach(module(function($provide) { + $provide.service('User', function($q) { + return { + getCurrent: function() { + var deferred = $q.defer(); + deferred.resolve( JSON.stringify(sampleUser) ); + return deferred.promise; + }, + login: function(credentials) { + var deferred = $q.defer(); + if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ + deferred.resolve( JSON.stringify(sampleUser) ); + }else { + deferred.resolve('Error: User could not be loggedin'); + } + + return deferred.promise; + }, + logout: function() { + var deferred = $q.defer(); + deferred.resolve(null); + return deferred.promise; + }, + signup: function(credentials) { + var deferred = $q.defer(); + if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){ + deferred.resolve( JSON.stringify(sampleUser) ); + }else { + deferred.resolve('Error: User could not be signed up'); + } + + return deferred.promise; + } + }; + }); + })); + + + // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). + // This allows us to inject a service but then attach it to a variable + // with the same name as the service. + beforeEach(inject(function($controller, $rootScope, _$state_, _$location_, _$stateParams_, _$httpBackend_, CurrentForm, Forms) { + // Set a new global scope + scope = $rootScope.$new(); + + //Set CurrentForm + CurrentForm.setForm(sampleForm); + + // Point global variables to injected services + $stateParams = _$stateParams_; + $httpBackend = _$httpBackend_; + $location = _$location_; + $state = _$state_; + + $httpBackend.whenGET(/\.html$/).respond(''); + $httpBackend.whenGET('/users/me/').respond(''); + + // Initialize the Forms controller. + createSubmitFormController = function(){ + return $controller('SubmitFormController', { $scope: scope }); + }; + })); + + + it('$scope.initForm() should populate $scope.myform with current Form', inject(function(Forms) { + + var controller = createSubmitFormController(); + + $stateParams.formId = '525a8422f6d0f87f0e407a33'; + + // Set GET response + $httpBackend.expectGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); + + // Run controller functionality + scope.initForm(); + $httpBackend.flush(); + $state.ensureAllTransitionsHappened(); + + // Test scope value + expect( scope.myform.toJSON() ).toEqualData(sampleForm); + expect( scope.hideNav ).toEqual(false); + })); + }); +}()); \ No newline at end of file diff --git a/public/modules/forms/views/directiveViews/form/submissions-form.client.view.html b/public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html similarity index 100% rename from public/modules/forms/views/directiveViews/form/submissions-form.client.view.html rename to public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html diff --git a/public/modules/forms/views/submit-form.client.view.html b/public/modules/forms/views/submit-form.client.view.html index 0e272e79..cbbc98a6 100644 --- a/public/modules/forms/views/submit-form.client.view.html +++ b/public/modules/forms/views/submit-form.client.view.html @@ -1,4 +1,4 @@ -
+