From 1fb36f9b4e267e89698ddf38b70ae535630d8153 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Thu, 20 Aug 2015 11:47:25 -0700 Subject: [PATCH] got ListFormsController tests to pass --- public/dist/application.js | 720 ++++++++++++++---- public/dist/application.min.css | 2 +- public/dist/application.min.js | 3 +- public/modules/core/css/core.css | 4 +- public/modules/core/css/select.css | 128 ++++ .../list-forms.client.controller.js | 35 +- public/modules/forms/css/form.css | 43 +- .../admin-from.client.controller.test.js | 2 +- .../list-forms.client.controller.test.js | 54 +- .../form/configure-form.client.view.html | 4 +- .../forms/views/list-forms.client.view.html | 39 +- .../authentication.client.controller.test.js | 6 +- 12 files changed, 837 insertions(+), 203 deletions(-) create mode 100644 public/modules/core/css/select.css diff --git a/public/dist/application.js b/public/dist/application.js index 51ce5695..7a06e50b 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -47,55 +47,55 @@ angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_RO superuser: 'superuser', }); -angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', - function($rootScope, Auth, $state, $stateParams) { +// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', +// function($rootScope, Auth, $state, $stateParams) { - $rootScope.$state = $state; - $rootScope.$stateParams = $stateParams; +// $rootScope.$state = $state; +// $rootScope.$stateParams = $stateParams; - // add previous state property - $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { - $state.previous = fromState; +// // add previous state property +// $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { +// $state.previous = fromState; - //Redirect to listForms if user is authenticated - if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){ - if(Auth.isAuthenticated()){ - event.preventDefault(); // stop current execution - $state.go('listForms'); // go to listForms page - } - } - //Redirect to 'home' route if user is not authenticated - else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){ - event.preventDefault(); // stop current execution - $state.go('home'); // go to listForms page - } +// //Redirect to listForms if user is authenticated +// if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){ +// if(Auth.isAuthenticated()){ +// event.preventDefault(); // stop current execution +// $state.go('listForms'); // go to listForms page +// } +// } +// //Redirect to 'home' route if user is not authenticated +// else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){ +// event.preventDefault(); // stop current execution +// $state.go('home'); // go to listForms page +// } - }); +// }); - } -]); +// } +// ]); -//Page access/authorization logic -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; +// //Page access/authorization logic +// 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; +// Auth.ensureHasCurrentUser(User); +// user = Auth.currentUser; - if(user){ - authenticator = new Authorizer(user); +// if(user){ +// authenticator = new Authorizer(user); - if( (permissions !== null) && !authenticator.canAccess(permissions) ){ - event.preventDefault(); - console.log('access denied') - $state.go('access_denied'); - } - } - }); -}]); +// if( (permissions !== null) && !authenticator.canAccess(permissions) ){ +// event.preventDefault(); +// console.log('access denied') +// $state.go('access_denied'); +// } +// } +// }); +// }]); //Then define the init function for starting up the application angular.element(document).ready(function() { @@ -442,21 +442,19 @@ angular.module('forms').config(['$stateProvider', 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 = false; // Find a specific Form - $scope.findOne = function() { + $scope.findOne = function(){ $scope.myform = Forms.get({ formId: $stateParams.formId }); CurrentForm.setForm($scope.myform); }; - - $scope.setForm = function (form) { + $scope.setForm = function(form){ $scope.myform = form; }; $rootScope.resetForm = function(){ @@ -468,83 +466,71 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope /* ** DeleteModal Functions */ - $scope.openDeleteModal = function() { - - deleteModal = $modal.open({ + $scope.openDeleteModal = function(){ + $scope.deleteModal = $modal.open({ animation: $scope.animationsEnabled, templateUrl: 'myModalContent.html', controller: 'AdminFormController', }); }; $scope.cancelDeleteModal = function(){ - if(deleteModal){ - deleteModal.dismiss('cancel'); + if($scope.deleteModal){ + $scope.deleteModal.dismiss('cancel'); } }; // Remove existing Form - $scope.remove = function(form_id) { - if(deleteModal && deleteModal.opened){ + $scope.removeCurrentForm = function() { + if($scope.deleteModal && $scope.deleteModal.opened){ - deleteModal.close(); + $scope.deleteModal.close(); - var form = {}; - if(!form_id){ - form = CurrentForm.getForm(); - if(!form) form = $scope.myform; - }else { - form._id = form_id; - } + 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) + $http.delete('/forms/'+form_id) .success(function(data, status, headers){ console.log('form deleted successfully'); - if(!form_id){ - $state.go('listForms', {}, {reload: true}); - } - if($scope.myforms.length > 0){ - $scope.myforms = _.filter($scope.myforms, function(myform){ - return myform._id !== form._id; - }); - } + $state.go('listForms', {}, {reload: true}); }).error(function(error){ console.log('ERROR: Form could not be deleted.'); console.error(error); - }).finally(function(){ - }); } }; - // Update existing Form - $scope.update = $rootScope.update = function(immediate, cb) { - // console.log('immediate: '+immediate); + $scope.update = $rootScope.update = function(updateImmediately, cb){ + var continueUpdate = true; - if(immediate){ - continueUpdate = !$rootScope.saveInProgress; + if(!updateImmediately){ + continueUpdate = !$rootScope.saveInProgress; } + //Update form if we **are not currently updating** or if **shouldUpdateNow flag is set** if(continueUpdate){ - console.log('begin updating form'); + // console.log('begin updating form'); var err = null; - if(immediate){ $rootScope.saveInProgress = true; } + if(!updateImmediately){ $rootScope.saveInProgress = true; } $scope.updatePromise = $http.put('/forms/'+$scope.myform._id, {form: $scope.myform}) .then(function(response){ $rootScope.myform = $scope.myform = response.data; - console.log(response.data); + // console.log(response.data); }).catch(function(response){ - console.log('Error occured during form UPDATE.\n'); - console.log(response.data); + // console.log('Error occured during form UPDATE.\n'); + // console.log(response.data); err = response.data; }).finally(function() { - console.log('finished updating'); - if(immediate){$rootScope.saveInProgress = false; } - cb(err); + // console.log('finished updating'); + if(!updateImmediately){$rootScope.saveInProgress = false; } + + if( (typeof cb) === 'function'){ + cb(err); + } }); } }; @@ -554,11 +540,12 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope 'use strict'; // Forms controller -angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm','$http', +angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) { $scope = $rootScope; - $rootScope.showCreateModal = false; + $scope.forms = {}; + $scope.showCreateModal = false; // Return all user's Forms $scope.findAll = function() { @@ -569,13 +556,13 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope //Modal functions $scope.openCreateModal = function(){ - if(!$rootScope.showCreateModal){ - $rootScope.showCreateModal = true; + if(!$scope.showCreateModal){ + $scope.showCreateModal = true; } }; $scope.closeCreateModal = function(){ - if($rootScope.showCreateModal){ - $rootScope.showCreateModal = false; + if($scope.showCreateModal){ + $scope.showCreateModal = false; } }; @@ -586,13 +573,14 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope $state.go(route, {'formId': id}, {reload: true}); }; - $scope.duplicate = function(form, form_index){ + $scope.duplicate = function(form_index){ + var form = $scope.myforms[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); + // console.log('form duplicated'); + $scope.myforms.splice(form_index+1, 0, data); }).error(function(errorResponse){ console.log(errorResponse); $scope.error = errorResponse.data.message; @@ -601,40 +589,36 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope // Create new Form $scope.createNew = function(){ - var form = {}; - form.title = $scope.myform.name.$modelValue; - form.language = $scope.myform.language.$modelValue; - // console.log(form); - $rootScope.showCreateModal = true; + console.log($scope.forms.createForm); - // console.log($scope.myform); - if($scope.myform.$valid && $scope.myform.$dirty){ + var form = {}; + form.title = $scope.forms.createForm.$modelValue; + form.language = $scope.forms.createForm.language.$modelValue; + + if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){ $http.post('/forms', {form: form}) .success(function(data, status, headers){ - console.log('form created'); + console.log('new form created'); // Redirect after save $scope.goToWithId('viewForm', data._id+''); }).error(function(errorResponse){ - console.log(errorResponse); + console.error(errorResponse); $scope.error = errorResponse.data.message; }); } }; - $scope.removeFromList = function(deleted_form_id) { + $scope.removeForm = function(form_index) { + if(form_index >= $scope.myforms.length || form_index < 0){ + throw new Error('Error: form_index in removeForm() must be between 0 and '+$scope.myforms.length-1); + } - console.log('Remove existing form'); - - $http.delete('/forms/'+deleted_form_id) + $http.delete('/forms/'+$scope.myforms[form_index]._id) .success(function(data, status, headers){ console.log('form deleted successfully'); - if($scope.myforms.length > 0){ - $scope.myforms = _.filter($scope.myforms, function(myform){ - return myform._id !== deleted_form_id; - }); - } + $scope.myforms.splice(form_index, 1); }).error(function(error){ console.log('ERROR: Form could not be deleted.'); @@ -714,12 +698,10 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun var debounceSave = function () { $rootScope.saveInProgress = true; - $rootScope[$attrs.autoSaveCallback](false, + $rootScope[$attrs.autoSaveCallback](true, function(err){ if(!err){ console.log('\n\nForm data persisted -- setting pristine flag'); - // console.log('\n\n---------\nUpdate form CLIENT'); - // console.log(Date.now()); $formCtrl.$setPristine(); }else{ console.error('Error form data NOT persisted'); @@ -728,7 +710,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun }); }; - + //Update/save Form if any Form fields are Dirty and Touched $scope.$watch(function(newValue, oldValue) { if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){ debounceSave(); @@ -763,7 +745,9 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun console.log('Saving Form'); debounceSave(); }); - }else if($rootScope.finishedRender && $rootScope.saveInProgress){ + } + //If we are finished rendering then form saving should be finished + else if($rootScope.finishedRender && $rootScope.saveInProgress){ $rootScope.saveInProgress = false; } @@ -816,6 +800,324 @@ angular.module('forms').directive('changeFocus', function() { }); 'use strict'; +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 = false; + $scope.languages = $rootScope.languages; + + var _current_upload = null; + $scope.resetForm = $rootScope.resetForm; + $scope.update = $rootScope.update; + + var _unbindedPdfFields = $scope.pdfFields; + + //DAVID: TODO: finish this so we can create a Form.pdfFieldMap + // $scope.getUnbindedPdfFields = function(fieldType){ + // _unbindedPdfFields = $scope.pdfFields + // } + + //PDF Functions + $scope.cancelUpload = function(){ + _current_upload.abort(); + $scope.pdfLoading = false; + $scope.removePDF(); + }; + + $scope.removePDF = function(){ + $scope.myform.pdf = null; + $scope.myform.isGenerated = false; + $scope.myform.autofillPDFs = false; + + console.log('form.pdf: '+$scope.myform.pdf+' REMOVED'); + }; + + $scope.uploadPDF = function(files) { + + if (files && files.length) { + // for (var i = 0; i < files.length; i++) { + 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.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; + $scope.myform.pdf = angular.fromJson(angular.toJson(data)); + + console.log($scope.myform.pdf); + + $scope.pdfLoading = false; + + console.log($scope.log); + if(!$scope.$$phase && !$scope.$digest){ + $scope.$apply(); + } + }).error(function(err){ + $scope.pdfLoading = false; + console.log('Error occured during upload.\n'); + console.log(err); + }); + } + }; + + } + }; + } +]); +'use strict'; + +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){ + + /* + ** Initialize scope with variables + */ + //Populate AddField with all available form field types + $scope.addField = {}; + $scope.addField.types = FormFields.fields; + + $scope.addField.types.forEach(function(type){ + type.lastAddedID = 1; + return type; + }); + + // Accordion settings + $scope.accordion = {}; + $scope.accordion.oneAtATime = true; + + //Populate local scope with rootScope methods/variables + $scope.update = $rootScope.update; + + /* + ** FormFields (ui-sortable) drag-and-drop configuration + */ + $scope.dropzone = { + handle: ' .handle' + }; + + + // $scope.draggable = { + // connectWith: ".dropzone", + // start: function (e, ui) { + // // $scope.$apply(function() { + // // $scope.dragging = true + // // }); + // $('.dropzone').sortable('refresh'); + // }, + // update: function (e, ui) { + // var isInDropzone = $(e.target).parentsUntil('.panel-group').hasClass('dropzone'); + + // console.log('isInDropzone: '+isInDropzone); + // //Disable drag and drop if we aren't in dropzone + // if(!isInDropzone){ + // ui.item.sortable.cancel(); + // } + // }, + // stop: function (e, ui) { + // var isInDropzone = $(e.target).parentsUntil('.panel-group').hasClass('dropzone'); + + // //Disable drag and drop if we aren't in dropzone + // if(isInDropzone){ + // console.log($(e.target)); + // } + + // // if (ui.item.sortable.droptarget === undefined) { + // // $scope.$apply($scope.dragging = false); + // // return; + // // }else if (ui.item.sortable.droptarget[0].classList[0] === "dropzone") { + // // // run code when item is dropped in the dropzone + // // $scope.$apply($scope.dragging = false); + // // }else{ + // // // $scope.$apply($scope.dragging = false); + // // } + // // 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; + // // } + + + // } + // }; + + + /* + ** Field CRUD Methods + */ + // Add a new field + $scope.addNewField = function(addOrReturn, fieldType){ + + // incr field_id counter + $scope.addField.lastAddedID++; + var fieldTitle; + + for(var i = 0; i < $scope.addField.types.length; i++){ + // console.log($scope.addField.types[i].name === fieldType); + if($scope.addField.types[i].name === fieldType){ + $scope.addField.types[i].lastAddedID++; + // console.log($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' : true, + 'disabled' : false, + }; + console.log('\n\n---------\nAdded field CLIENT'); + console.log(newField); + + // put newField into fields array + if(addOrReturn){ + $scope.myform.form_fields.push(newField); + }else { + return newField; + } + + + // console.log(Date.now()); + // console.log($scope.myform.form_fields.length); + }; + + // deletes particular field on button click + $scope.deleteField = function (hashKey){ + // console.log($scope.myform.form_fields); + for(var i = 0; i < $scope.myform.form_fields.length; i++){ + // console.log($scope.myform.form_fields[i].$$hashKey === hashKey); + 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(false, $scope.myform.form_fields[field_index].fieldType); + field.title = $scope.myform.form_fields[field_index].title; + console.log($scope.myform.form_fields[field_index]); + + //Insert field at selected index + $scope.myform.form_fields.splice(field_index+1, 0, field); + + }; + + + /* + ** startPage Button Methods + */ + + // add new Button to the startPage/EndPage + $scope.addButton = function (newButtons){ + + var newButton = {}; + newButton.bgColor = '#ddd'; + newButton.color = '#ffffff'; + newButton.text = 'Button'; + + $scope.myform.startPage.buttons.push(newButton); + }; + + // delete particular Button + $scope.deleteButton = function(button){ + 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();; + + if(currHashKey === hashKey){ + $scope.myform.startPage.buttons.splice(i, 1); + break; + } + } + }; + + + + /* + ** Field Option Methods + */ + + // add new option to the field + $scope.addOption = function (field){ + if(!field.fieldOptions) field.fieldOptions = []; + + var lastOptionID = 0; + + if(field.fieldOptions[field.fieldOptions.length-1]) + lastOptionID = field.fieldOptions[field.fieldOptions.length-1].option_id; + + // new option's id + var option_id = lastOptionID + 1; + + var newOption = { + 'option_id' : option_id, + 'option_title' : 'Option ' + option_id, + 'option_value' : option_id + }; + + // put new option into fieldOptions array + field.fieldOptions.push(newOption); + }; + + // delete particular option + $scope.deleteOption = function (field, option){ + for(var i = 0; i < field.fieldOptions.length; i++){ + if(field.fieldOptions[i].option_id === option.option_id){ + field.fieldOptions.splice(i, 1); + break; + } + } + }; + + // decides whether field options block will be shown (true for dropdown and radio fields) + $scope.showAddOptions = function (field){ + if(field.fieldType === 'dropdown' || field.fieldType === 'checkbox' || field.fieldType === 'radio'){ + return true; + } else { + return false; + } + }; + + }, + + }; + } +]); +'use strict'; + angular.module('forms').directive('fieldIconDirective', function($http, $compile) { return { @@ -962,6 +1264,159 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo 'use strict'; +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: false, + rows: [] + }; + + /* + ** Table Functions + */ + $scope.isAtLeastOneChecked = function(){ + // console.log('isAtLeastOneChecked'); + for(var i=0; i<$scope.table.rows.length; i++){ + if($scope.table.rows[i].selected) return true; + } + return false; + }; + $scope.toggleAllCheckers = function(){ + // console.log('toggleAllCheckers'); + 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; + }; + + /* + * Form Submission Methods + */ + //Delete selected submissions of Form + $scope.deleteSelectedSubmissions = function(){ + // console.log('deleteSelectedSubmissions'); + 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){ + //Remove deleted ids from table + var tmpArray = []; + for(var i=0; i<$scope.table.rows.length; i++){ + if(!$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; + }); + }; + + //Export selected submissions of Form + $scope.exportSubmissions = function(type){ + var fileMIMETypeMap = { + 'xls': 'vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'json': 'json', + 'csv': 'csv', + }; + + var 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); + }; + + + //Fetch and display submissions of Form + $scope.showSubmissions = function(){ + $http.get('/forms/'+$scope.myform._id+'/submissions') + .success(function(data, status, headers){ + + var _data = [], + _currentSubmission, + _tmpSubFormFields, + defaultFormFields = JSON.parse(JSON.stringify($scope.myform.form_fields)); + + + //Iterate through form's submissions + for(var i=0; i*{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}}.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{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}.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}.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 diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 2bdbc2cf..3e8b44c3 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,2 +1 @@ -"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/view-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("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").controller("ViewFormController",["$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.viewSubmissions=!1,$scope.table={masterChecker:!1,rows:[]},$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.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(){var blob=new Blob([document.getElementById("table-submission-data").innerHTM],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"});saveAs(blob,$scope.myform.title+"_export_"+Date.now()+".xls")},$scope.showSubmissions=function(){$scope.viewSubmissions=!0,$http.get("/forms/"+$scope.myform._id+"/submissions").success(function(data,status,headers){for(var _data=[],i=0;i0&&($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){console.log("immediate: "+immediate);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").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("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.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.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(Button){var lastButtonID=0;$scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1]&&(lastButtonID=$scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1].button_id),Button.backgroundColor="#5bc0de",Button.button_id=lastButtonID,Button.color="#ffffff",$scope.myform.StartPage.buttons.push(Button)},$scope.deleteButton=function(button_index){$scope.myform.StartPage.buttons.splice(button_index,1)},$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("formLocator",function(){return{link:function(scope){scope.$emit("formLocator")}}}),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.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{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.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 diff --git a/public/modules/core/css/core.css b/public/modules/core/css/core.css index 8524864c..bd98ab4a 100755 --- a/public/modules/core/css/core.css +++ b/public/modules/core/css/core.css @@ -52,10 +52,10 @@ display: none !important; } .ng-invalid.ng-dirty { - border-color: #FA787E; + /*border-color: #FA787E;*/ } .ng-valid.ng-dirty { - border-color: #78FA89; + /*border-color: #78FA89;*/ } .browsehappy.jumbotron.hide, body.ng-cloak diff --git a/public/modules/core/css/select.css b/public/modules/core/css/select.css new file mode 100644 index 00000000..76b9aaf7 --- /dev/null +++ b/public/modules/core/css/select.css @@ -0,0 +1,128 @@ + +/* Container used for styling the custom select, the buttom class below adds the bg gradient, corners, etc. */ +.custom-select { + position: relative; + display:block; + padding:0; +} + + +/* This is the native select, we're making everything but the text invisible so we can see the button styles in the wrapper */ +.custom-select select { + width:100%; + margin:0; + background:none; + border: 1px solid transparent; + border-radius: 0px; + outline: none; + /* Prefixed box-sizing rules necessary for older browsers */ + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + /* Remove select styling */ + appearance: none; + -webkit-appearance: none; + /* Font size must the 16px or larger to prevent iOS page zoom on focus */ + font-size:1em; + /* General select styles: change as needed */ + font-family: helvetica, sans-serif; + font-weight: bold; + color: #444; + padding: .6em 1.9em .5em .8em; + line-height:1.3; +} + + +/* Custom arrow sits on top of the select - could be an image, SVG, icon font, etc. or the arrow could just baked into the bg image on the select. Note this si a 2x image so it will look bad in browsers that don't support background-size. In production, you'd handle this resolution switch via media query but this is a demo. */ + +.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; + /* This hack make the select behind the arrow clickable in some browsers */ + pointer-events:none; +} + + +/* Hover style */ +.custom-select:hover { + border:1px solid #888; +} + +/* Focus style */ +.custom-select select:focus { + outline:none; + box-shadow: 0 0 1px 3px rgba(180,222,250, 1); + background-color:transparent; + color: #222; + border:1px solid #aaa; +} + +/* Set options to normal weight */ +.custom-select option { + font-weight:normal; +} + + + + + + +/* ------------------------------------ */ +/* START OF UGLY BROWSER-SPECIFIC HACKS */ +/* ---------------------------------- */ + +/* OPERA - Pre-Blink nix the custom arrow, go with a native select button to keep it simple. Targeted via this hack http://browserhacks.com/#hack-a3f166304aafed524566bc6814e1d5c7 */ +x:-o-prefocus, .custom-select::after { + display:none; +} + + /* IE 10/11+ - This hides native dropdown button arrow so it will have the custom appearance, IE 9 and earlier get a native select - targeting media query hack via http://browserhacks.com/#hack-28f493d247a12ab654f6c3637f6978d5 - looking for better ways to achieve this targeting */ +/* The second rule removes the odd blue bg color behind the text in the select button in IE 10/11 and sets the text color to match the focus style's - fix via http://stackoverflow.com/questions/17553300/change-ie-background-color-on-unopened-focused-select-box */ +@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: transparent; + color: #222; + } +} + + +/* FIREFOX won't let us hide the native select arrow, so we have to make it wider than needed and clip it via overflow on the parent container. The percentage width is a fallback since FF 4+ supports calc() so we can just add a fixed amount of extra width to push the native arrow out of view. We're applying this hack across all FF versions because all the previous hacks were too fragile and complex. You might want to consider not using this hack and using the native select arrow in FF. Note this makes the menus wider than the select button because they display at the specified width and aren't clipped. Targeting hack via http://browserhacks.com/#hack-758bff81c5c32351b02e10480b5ed48e */ +/* Show only the native arrow */ +@-moz-document url-prefix() { + .custom-select { + overflow: hidden; + } + .custom-select select { + width: 120%; + width: -moz-calc(100% + 3em); + width: calc(100% + em); + } + +} + +/* Firefox focus has odd artifacts around the text, this kills that. See https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-focusring */ +.custom-select select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #000; +} + + + +/* ------------------------------------ */ +/* END OF UGLY BROWSER-SPECIFIC HACKS */ +/* ------------------------------------ */ + + + \ No newline at end of file diff --git a/public/modules/forms/controllers/list-forms.client.controller.js b/public/modules/forms/controllers/list-forms.client.controller.js index 52f54043..a2f47873 100644 --- a/public/modules/forms/controllers/list-forms.client.controller.js +++ b/public/modules/forms/controllers/list-forms.client.controller.js @@ -5,7 +5,8 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) { $scope = $rootScope; - $rootScope.showCreateModal = false; + $scope.forms = {}; + $scope.showCreateModal = false; // Return all user's Forms $scope.findAll = function() { @@ -16,13 +17,13 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope //Modal functions $scope.openCreateModal = function(){ - if(!$rootScope.showCreateModal){ - $rootScope.showCreateModal = true; + if(!$scope.showCreateModal){ + $scope.showCreateModal = true; } }; $scope.closeCreateModal = function(){ - if($rootScope.showCreateModal){ - $rootScope.showCreateModal = false; + if($scope.showCreateModal){ + $scope.showCreateModal = false; } }; @@ -34,13 +35,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; @@ -49,22 +51,21 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope // Create new Form $scope.createNew = function(){ - var form = {}; - form.title = $scope.myform.name.$modelValue; - form.language = $scope.myform.language.$modelValue; - // console.log(form); - $rootScope.showCreateModal = true; + console.log($scope.forms.createForm); - // console.log($scope.myform); - if($scope.myform.$valid && $scope.myform.$dirty){ + var form = {}; + form.title = $scope.forms.createForm.title.$modelValue; + form.language = $scope.forms.createForm.language.$modelValue; + + if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){ $http.post('/forms', {form: form}) .success(function(data, status, headers){ - console.log('form created'); + console.log('new form created'); // Redirect after save $scope.goToWithId('viewForm', data._id+''); }).error(function(errorResponse){ - console.log(errorResponse); + console.error(errorResponse); $scope.error = errorResponse.data.message; }); } diff --git a/public/modules/forms/css/form.css b/public/modules/forms/css/form.css index 142f1fec..324c2118 100644 --- a/public/modules/forms/css/form.css +++ b/public/modules/forms/css/form.css @@ -1,8 +1,6 @@ .panel-default.startPage { - - /*background-color: #eee;*/ border-style: dashed; - border-color: #a9a9a9; + border-color: #a9a9a9; border-width:3px; } @@ -11,7 +9,7 @@ section.content p { } .btn { - border: 1px solid #c6c6c6!important; + border: 1px solid #c6c6c6; } .btn[type='submit'] { font-size: 1.5em; @@ -190,8 +188,6 @@ div.config-form .row.field { } - - /* Styles for form admin view (/forms/:formID/admin) */ .admin-form > .page-header { padding-bottom: 0px; @@ -321,7 +317,9 @@ section > section.public-form { margin-bottom: 45px; } .form-item.create-new input[type='text']{ - /*width: inherit;*/ + width: inherit; + color:black; + border:none; } .form-item.create-new { @@ -329,7 +327,7 @@ section > section.public-form { color: white; } -/*MODAL CSS */ +/*CREATE-NEW FORM MODAL*/ .form-item.create-new.new-form { background-color: rgb(300,131,131); z-index: 11; @@ -337,9 +335,34 @@ section > section.public-form { .form-item.create-new.new-form:hover { background-color: rgb(300,100,100); } + .form-item.new-form input[type='text'] { + margin-top:0.2em; + width: inherit; + color:black; + border:none; + padding: 0.3em 0.6em 0.3em 0.6em; + } + .form-item.new-form .custom-select { + margin-top: 0.2em + } + .form-item.new-form .custom-select select { + background-color: white; + } - .form-item.new-form a.btn { - font-size: 0.95em; + + .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: 0.95em; + } + + .form-item.new-form .title-row { + margin-top: 1em; + top:0; } /*Modal overlay (for lightbox effect)*/ diff --git a/public/modules/forms/tests/admin-from.client.controller.test.js b/public/modules/forms/tests/admin-from.client.controller.test.js index de20eca5..dda89056 100644 --- a/public/modules/forms/tests/admin-from.client.controller.test.js +++ b/public/modules/forms/tests/admin-from.client.controller.test.js @@ -214,7 +214,7 @@ it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', function() { var controller = createAdminFormController(); - //Set expected $state transition + //Set $state transition $state.expectTransitionTo('listForms'); // Set DELETE response 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 5cc7e7cb..769d9e75 100644 --- a/public/modules/forms/tests/list-forms.client.controller.test.js +++ b/public/modules/forms/tests/list-forms.client.controller.test.js @@ -192,38 +192,37 @@ var dupSampleForm = sampleFormList[2], dupSampleForm_index = 3, - newSampleFormList = sampleFormList; + newSampleFormList = _.clone(sampleFormList); dupSampleForm._id = 'a02df75b44c1d26b6a5e05b8'; - newSampleFormList.splice(2, 0, dupSampleForm); + newSampleFormList.splice(3, 0, dupSampleForm); var controller = createListFormsController(); // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - + $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); // Run controller functionality scope.findAll(); $httpBackend.flush(); // Set GET response $httpBackend.expect('POST', '/forms').respond(200, dupSampleForm); - // Run controller functionality scope.duplicate(2); $httpBackend.flush(); // Test scope value - expect( scope.myforms.length ).toEqual(sampleFormList.length+1); - // expect( scope.myforms ).toEqualData(newSampleFormList); + expect( scope.myforms.length ).toEqual(newSampleFormList.length); + for(var i=0; i + style="width: 100%;" + ng-minlength="4" + ng-pattern="/^[a-zA-Z0-9 \-.]*$/"> diff --git a/public/modules/forms/views/list-forms.client.view.html b/public/modules/forms/views/list-forms.client.view.html index d57cb485..2c541a42 100644 --- a/public/modules/forms/views/list-forms.client.view.html +++ b/public/modules/forms/views/list-forms.client.view.html @@ -21,33 +21,32 @@ -
-
-
-
Name
-
- -
-
-
-
- Language + +
+
Name
+
+
-
+
+
+
Language
+
+
-
-
-
- -
-
+
+
+
+
+ +
+
diff --git a/public/modules/users/tests/authentication.client.controller.test.js b/public/modules/users/tests/authentication.client.controller.test.js index a5f281ed..bcdcb4c0 100755 --- a/public/modules/users/tests/authentication.client.controller.test.js +++ b/public/modules/users/tests/authentication.client.controller.test.js @@ -36,13 +36,11 @@ // var firstname = element(by.model('credentials.firstname')), // lastname = element(by.model('credentials.lastname')), // email = element(by.model('credentials.email')), -// password = element(by.model('credentials.password')), -// username = element(by.model('credentials.username')); +// password = element(by.model('credentials.password')); // email.sendKeys('admin@app.com'); -// username.sendKeys('admin'); // firstname.sendKeys('admin_first'); -// firstname.sendKeys('admin_last'); +// lastname.sendKeys('admin_last'); // password.sendKeys('1234'); // //Click signup button