From 3d633578310df3cd82fcb3820126a342fcc2d7cf Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Wed, 5 Aug 2015 15:24:24 -0700 Subject: [PATCH] fixed autosaving --- docs/ux_flows.md | 29 ++ public/dist/application.js | 484 +++++++++++------- public/dist/application.min.css | 2 +- public/dist/application.min.js | 4 +- .../view-form.client.controller.js | 21 +- public/modules/forms/css/form.css | 3 +- .../directives/auto-save.client.directive.js | 187 ++++--- .../directives/edit-form.client.directive.js | 47 +- .../on-finish-render.client.directive.js | 3 +- .../cgBusy/updateFormLoading.html | 3 + .../directiveViews/form/configure-form.html | 2 +- .../views/directiveViews/form/edit-form.html | 298 +++++------ .../forms/views/view-form.client.view.html | 7 +- 13 files changed, 673 insertions(+), 417 deletions(-) create mode 100644 docs/ux_flows.md create mode 100644 public/modules/forms/views/directiveViews/cgBusy/updateFormLoading.html diff --git a/docs/ux_flows.md b/docs/ux_flows.md new file mode 100644 index 00000000..847b2853 --- /dev/null +++ b/docs/ux_flows.md @@ -0,0 +1,29 @@ +UX of Updating Forms +==================== + +##Form Updating + - Action: Update Configuration + 1. User clicks on Form from FormList page (visits form admin page) + 2. User clicks on "Configure Form" Tab + 3. User changes inputs in form page + 4. Save Button is Pressed + 5. Loading/Busy Indicator fills the screen + 6. Loading/Busy Indicator exits the screen + 7. Configuration page is shown with updated settings + + - Action: Add Form Field + 1. User clicks on Form from FormList page + 2. User clicks on a Tab in "AddField" column + 3. Loading/Busy Indicator fills the screen + 4. Loading/Busy Indicator exits the screen + + - Action: Edit Form Field Title + 1. User clicks on Form from FormList page (visits form admin page) + 2. User clicks on a current Form Input accordion (must be either the name or the caret) + 3. The clicked accordion (the one interacted with in Step#2) expands + 4. User clicks on 'Question Title' text input (aka focuses on said text input) + 5. User starts typing in text input + 6. User defocuses/clicks off of text input + 7. Loading/Busy Indicator fills the screen + 8. Loading/Busy Indicator exits the screen + 9. Field Accordion heading is updated diff --git a/public/dist/application.js b/public/dist/application.js index 2b3c3347..c1ac1b24 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -451,11 +451,9 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope // Return all user's Forms $scope.findAll = function() { - if(!$scope.myforms){ - Forms.query(function(_forms){ - $scope.myforms = _forms; - }); - } + Forms.query(function(_forms){ + $scope.myforms = _forms; + }); }; //Modal functions @@ -473,6 +471,9 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope $scope.setForm = function (form) { $scope.myform = form; }; + $scope.goToWithId = function(route, id) { + $state.go(route, {'formId': id}, {reload: true}); + }; // Create new Form $scope.createNew = function(){ @@ -498,6 +499,37 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope }); } }; + + $scope.remove = function(form_id) { + + console.log('Remove existing form'); + + var form = {}; + if(!form_id){ + form = CurrentForm.getForm(); + if(!form) form = $scope.myform; + }else { + form._id = 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; + }); + } + + }).error(function(error){ + console.log('ERROR: Form could not be deleted.'); + console.error(error); + }); + }; } ]); 'use strict'; @@ -535,10 +567,12 @@ angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScop 'use strict'; // Forms controller -angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm','$http', - function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) { +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 = false; $scope.viewSubmissions = false; @@ -555,13 +589,14 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope' CurrentForm.setForm($scope.myform); }; - $scope.goToWithId = function(route, id) { - $state.go(route, {'formId': id}, {reload: true}); - }; - $scope.setForm = function (form) { $scope.myform = form; }; + $rootScope.resetForm = function(){ + $scope.myform = Forms.get({ + formId: $stateParams.formId + }); + }; /* * Table Functions @@ -673,33 +708,57 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope' $scope.viewSubmissions = false; }; + /* + ** DeleteModal Functions + */ + $scope.openDeleteModal = function() { + + deleteModal = $modal.open({ + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + controller: 'ViewFormController', + }); + }; + $scope.cancelDeleteModal = function(){ + if(deleteModal){ + deleteModal.dismiss('cancel'); + } + }; + // Remove existing Form $scope.remove = function(form_id) { - var form = {}; - if(!form_id){ - form = CurrentForm.getForm(); - if(!form) form = $scope.myform; - }else { - form._id = form_id; + if(deleteModal && deleteModal.opened){ + + deleteModal.close(); + + var form = {}; + if(!form_id){ + form = CurrentForm.getForm(); + if(!form) form = $scope.myform; + }else { + form._id = 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; + }); + } + + }).error(function(error){ + console.log('ERROR: Form could not be deleted.'); + console.error(error); + }).finally(function(){ + + }); } - - $http.delete('/forms/'+form._id) - .success(function(data, status, headers){ - console.log('form deleted successfully'); - - if(!form_id){ - $state.go('listForms'); - } - if($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); - }); }; @@ -730,12 +789,6 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope' } }; - $rootScope.resetForm = function(){ - $scope.myform = Forms.get({ - formId: $stateParams.formId - }); - }; - } ]); 'use strict'; @@ -743,95 +796,127 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope' angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', function($rootScope, $timeout) { return { - require: ['^form'], - // scope: { - // callback: '&autoSaveCallback' - // }, + // require: ['^form'], + restrict: 'AE', link: function($scope, $element, $attrs, $ctrls) { + angular.element(document).ready(function() { + $rootScope.finishedRender = false; - $rootScope.finishedRender = false; - if($rootScope.watchCount === undefined){ - $rootScope.watchCount = 0; - } + // Log that the directive has been linked. + // console.log( "Linked: autoSaveForm"); - var difference = function(array){ - var rest = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1)); + var $formCtrl = $scope.editForm, + savePromise = null; - var containsEquals = function(obj, target) { - if (obj === null) return false; - return _.any(obj, function(value) { - return _.isEqual(value, target); - }); + + $scope.$on('editFormFieldsStarted', function(ngRepeatFinishedEvent) { + $rootScope.finishedRender = false; + }); + $scope.$on('editFormFieldsFinished', function(ngRepeatFinishedEvent) { + $rootScope.finishedRender = true; + }); + + $scope.anyDirtyAndTouched = function (form){ + for(var prop in form) { + if(form.hasOwnProperty(prop) && prop[0] !== '$') { + + // console.log(form[prop]); + if(form[prop].$dirty && form[prop].$untouched) { + return true; + } + } + } + return false; }; - return _.filter(array, function(value){ return !containsEquals(rest, value); }); - }; + // console.log('properties of $scope.editForm'); + // for(var item in $scope.editForm){ + // console.log(item); + // } - var $formCtrl = $ctrls[0]; - var savePromise = null; - // $scope.finishedRender = false; - var expression = $attrs.autoSaveForm || 'true'; + // console.log($scope.editForm); + // console.log($scope.watchModel); - $scope.$on('ngRepeatStarted', function(ngRepeatFinishedEvent) { - $rootScope.finishedRender = false; - $rootScope.watchCount = 0; - }); - $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) { - $rootScope.finishedRender = true; - }); + //Autosave Form when model (specificed in $attrs.autoSaveWatch) changes + $scope.$watch($attrs.autoSaveWatch, function(newValue, oldValue) { + if( !newValue && !oldValue ){ + return; + } + var changedFields = !_.isEqual(oldValue,newValue); - $scope.$watch('myform.form_fields', function(newValue, oldValue) { - console.log('watchCount: '+$rootScope.watchCount); - if(difference(oldValue,newValue).length === 0 || oldValue === undefined){ - return; - } - - // console.log('\n\n----------\n$dirty: '+( $formCtrl.$dirty ) ); - // console.log('form_fields changed: '+difference(oldValue,newValue).length ); - // console.log('$valid: '+$formCtrl.$valid); - // console.log('finishedRender: '+$rootScope.finishedRender); - // console.log('saveInProgress: '+$rootScope.saveInProgress); - - if($rootScope.finishedRender && ($formCtrl.$dirty || difference(oldValue,newValue).length !== 0) && !$rootScope.saveInProgress) { - $rootScope.watchCount++; - - // if($rootScope.watchCount === 1) { - - if(savePromise) { - $timeout.cancel(savePromise); - } - - savePromise = $timeout(function() { - savePromise = null; - - $rootScope[$attrs.autoSaveCallback]( - function(err){ - if(!err){ - console.log('\n\nForm data persisted -- setting pristine flag'); - // console.log('\n\n---------\nUpdate form CLIENT'); - // console.log(Date.now()); - $rootScope.watchCount = 0; - $formCtrl.$setPristine(); - // $rootScope.saveInProgress = false; - }else{ - console.log('Error form data NOT persisted'); - console.log(err); - } - }); - - }); + // console.log('\n\n----------'); + // console.log('$dirty: '+ $formCtrl.$dirty ); + // console.log('oldValue: '+oldValue); + // console.log('newValue: '+newValue); + // console.log('form_fields changed: '+changedFields); + // console.log('finishedRender: '+$rootScope.finishedRender); + // console.log('saveInProgress: '+$rootScope.saveInProgress); + // console.log($scope.editForm); + var inputDirtyUntouched = $scope.anyDirtyAndTouched($scope.editForm); + // console.log('properties of $scope.editForm'); + // for(var item in $scope.editForm){ + // console.log(item); // } - }else{ - return; - } - - }, true); + + // console.log('inputDirtyUntouched: '+inputDirtyUntouched); + // console.log($scope.editForm); + + //Save form ONLY IF rendering is finished, form_fields have been change AND currently not save in progress + if($rootScope.finishedRender && ($formCtrl.$dirty || changedFields) && !$rootScope.saveInProgress) { + + console.log('Saving Form'); + if(savePromise) { + $timeout.cancel(savePromise); + } + + savePromise = $timeout(function() { + savePromise = null; + + $rootScope[$attrs.autoSaveCallback]( + 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(); + // $formCtrl.$setUntouched(); + }else{ + console.error('Error form data NOT persisted'); + console.error(err); + } + }); + + }); + + // } + }else{ + return; + } + }, true); + + }); + } }; }]); + +'use strict'; + +angular.module('forms').directive('bnLifecycle',['$rootScope', function($rootScope) { + return { + // I link the DOM element to the view model. + restrict: 'A', + link: function( scope, element, attributes ) { + // Log that the directive has been linked. + console.log('aoeuaoeu'); + // console.log( 'Linked:', attributes.id ); + } + }; +}]); + 'use strict'; angular.module('forms').directive('changeFocus', function() { @@ -873,6 +958,14 @@ angular.module('forms').directive('changeFocus', function() { 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 = false; @@ -943,30 +1036,43 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt } }; - }, - templateUrl: './modules/forms/views/directiveViews/form/configure-form.html', - restrict: 'E', - scope: { - myform:'=', - user:'=', - pdfFields:'@', - formFields:'@' } }; } ]); 'use strict'; -angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields', +angular.module('forms') +.directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields', function ($rootScope, $q, $http, $timeout, timeCounter, Auth, FormFields) { return { templateUrl: './modules/forms/views/directiveViews/form/edit-form.html', restrict: 'E', scope: { myform:'=', - user:'=' }, + // transclude: true, controller: function($scope){ + + // Log that the directive has been linked. + // console.log( "Linked: editForm Controller"); + + /* + ** 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; @@ -977,7 +1083,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht handle: ' .handle' } - console.log($scope.myform); + // console.log($scope.myform); // $scope.draggable = { // connectWith: ".dropzone", @@ -1024,19 +1130,9 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht // }; - //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; - + /* + ** Field CRUD Methods + */ // Add a new field $scope.addNewField = function(fieldType){ @@ -1088,6 +1184,10 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht } }; + /* + ** Field Option Methods + */ + // add new option to the field $scope.addOption = function (field){ if(!field.fieldOptions) field.fieldOptions = []; @@ -1139,7 +1239,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht angular.module('forms').directive('fieldIconDirective', function($http, $compile) { return { - templateUrl: './modules/forms/views/directiveViews/form/fieldIcon.html', + template: '', restrict: 'E', scope: { typeName: '@' @@ -1160,6 +1260,7 @@ angular.module('forms').directive('fieldIconDirective', function($http, $compile 'scale': 'fa fa-sliders', 'stripe': 'fa fa-credit-card', 'statement': 'fa fa-quote-left', + 'yes_no': 'fa fa-toggle-on' } $scope.typeIcon = iconTypeMap[$scope.typeName]; }, @@ -1196,7 +1297,8 @@ angular.module('forms').directive('fieldDirective', function($http, $compile) { 'legal', 'statement', 'rating', - 'yes_no' + 'yes_no', + 'natural' ]; if (__indexOf.call(supported_fields, type) >= 0) { return templateUrl += type + '.html'; @@ -1204,7 +1306,6 @@ angular.module('forms').directive('fieldDirective', function($http, $compile) { }; var linker = function(scope, element) { - // scope.field.required = scope.required; //Set format only if field is a date if(scope.field.fieldType === 'date'){ @@ -1216,6 +1317,15 @@ angular.module('forms').directive('fieldDirective', function($http, $compile) { defaultDate: 0, }; } + //Set only if we have a natural lang processing field + else if(scope.field.fieldType === 'natural'){ + scope.field.fieldMatchValue = ''; + + //Fires when field is changed + scope.$watch('scope.field', function(newField, oldField) { + + }); + } // GET template content from path var templateUrl = getTemplateUrl(scope.field); @@ -1248,17 +1358,27 @@ angular.module('forms').directive('formLocator', function() { angular.module('forms').directive('onFinishRender', function ($rootScope, $timeout) { return { restrict: 'A', - link: function (scope, element, attr) { - if (scope.$first === true) { - $timeout(function () { - $rootScope.$broadcast('ngRepeatStarted'); - }); + link: function (scope, element, attrs) { + + //Don't do anything if we don't have a ng-repeat on the current element + if(!element.attr('ng-repeat')){ + return; } - if (scope.$last === true) { - console.log(element); + + var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; + + + if(scope.$first && !scope.$last) { + $timeout(function () { + // console.log(broadcastMessage+'Started'); + $rootScope.$broadcast(broadcastMessage+'Started'); + }); + }else if(scope.$last) { $timeout(function () { - console.log('ngRepeatFinished') - $rootScope.$broadcast('ngRepeatFinished'); + element.ready(function () { + // console.log(broadcastMessage+'Finished'); + $rootScope.$broadcast(broadcastMessage+'Finished'); + }); }); } } @@ -1267,45 +1387,49 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo 'use strict'; -angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', - function ($http, $timeout, timeCounter, Auth) { +angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', '$filter', + function ($http, $timeout, timeCounter, Auth, $filter) { return { + templateUrl: './modules/forms/views/directiveViews/form/submit-form.html', + restrict: 'E', + scope: { + form:'=' + }, controller: function($scope){ + console.log('rendering submitFormDirective'); timeCounter.startClock(); $scope.submit = function(){ var _timeElapsed = timeCounter.stopClock(); $scope.form.timeElapsed = _timeElapsed; - // console.log($scope.form.timeElapsed); - $scope.authentication = Auth; - console.log($scope.authentication.isAuthenticated()); + $scope.form.percentageComplete = $filter('formValidity')($scope.form.visible_form_fields)/$scope.visible_form_fields.length; + delete $scope.form.visible_form_fields; - $scope.submitPromise = $http.post('/forms/'+$scope.form._id,$scope.form). - success(function(data, status, headers){ - console.log('form submitted successfully'); - // alert('Form submitted..'); - $scope.form.submitted = true; - }) - .error(function(error){ - console.log(error); - $scope.error = error.message; - }); + $scope.authentication = Auth; + + $scope.submitPromise = $http.post('/forms/'+$scope.form._id,$scope.form) + .success(function(data, status, headers){ + console.log('form submitted successfully'); + // alert('Form submitted..'); + $scope.form.submitted = true; + }) + .error(function(error){ + console.log(error); + $scope.error = error.message; + }); }; $scope.reloadForm = function(){ + timeCounter.stopClock(); + timeCounter.startClock(); $scope.form.submitted = false; $scope.form.form_fields = _.chain($scope.form.form_fields).map(function(field){ field.fieldValue = ''; return field; }).value(); - } + }; - }, - templateUrl: './modules/forms/views/directiveViews/form/submit-form.html', - restrict: 'E', - scope: { - form:'=' } }; } @@ -1378,7 +1502,7 @@ angular.module('forms').service('FormFields', [ }, { name : 'dropdown', - value : 'Dropdown List' + value : 'Dropdown' }, { name : 'date', @@ -1386,7 +1510,7 @@ angular.module('forms').service('FormFields', [ }, { name : 'textarea', - value : 'Long Text' + value : 'Paragraph Text' }, { name : 'checkbox', @@ -1394,13 +1518,17 @@ angular.module('forms').service('FormFields', [ }, { name : 'yes_no', - value : 'Yes or No' + value : 'Yes/No' }, { name : 'legal', value : 'Legal' }, // { + // name : 'sig', + // value : 'Signature' + // }, + // { // name : 'file', // value : 'File Upload' // }, @@ -1424,6 +1552,10 @@ angular.module('forms').service('FormFields', [ name : 'statement', value : 'Statement' }, + { + name : 'natural', + value : 'Natural Language Input' + }, ]; } @@ -1864,9 +1996,9 @@ angular.module('users').factory('Auth', function($window) { // because that would create a circular dependency // Auth <- $http <- $resource <- LoopBackResource <- User <- Auth ensureHasCurrentUser: function(User) { - if (service.currentUser && service.currentUser.displayName) { + if (service.currentUser && service.currentUser.username) { console.log('Using local current user.'); - console.log(service.currentUser); + // console.log(service.currentUser); return service.currentUser; } else if ($window.user){ diff --git a/public/dist/application.min.css b/public/dist/application.min.css index df78996e..5c07014f 100644 --- a/public/dist/application.min.css +++ b/public/dist/application.min.css @@ -1 +1 @@ -.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown a.dropdown-toggle>*{color:#d9d9d9}.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}.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:absolute;top:0;left:0;height:230%;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:absolute;top:0;left:0;height:230%;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}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}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 .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .row.field>.field-input>input.text-field-input,form .row.field>.field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .row.field>.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}div.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);width:90%}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-top:1.2em;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}.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 .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}.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}.status-light{padding-left:.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.row{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;height:215px;margin-bottom:45px}.form-item.row.create-new{background-color:#838383;color:#fff}.form-item.row.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.row.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form a.btn{font-size:.95em}.overlay{position:absolute;top:0;left:0;height:193%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.form-item.row.create-new:hover,.form-item.row:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.row.create-new:hover{background-color:#515151}.form-item.row>.title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item.row>.title-row h4{font-size:1.3em}.form-item.row.create-new>.title-row{padding:0}.form-item.row.create-new>.title-row h4{font-size:7em}.form-item.row>.details-row{margin-top:3.2em}.form-item.row>.details-row small{font-size:.6em}.form-item.row.create-new>.details-row small{font-size:.95em}@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 a.dropdown-toggle>*{color:#d9d9d9}.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}.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:absolute;top:0;left:0;height:230%;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:absolute;top:0;left:0;height:230%;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}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 .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .row.field>.field-input>input.text-field-input,form .row.field>.field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .row.field>.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}div.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);width:90%}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-top:1.2em;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}.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 .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}.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}.status-light{padding-left:.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.row{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;height:215px;margin-bottom:45px}.form-item.row.create-new{background-color:#838383;color:#fff}.form-item.row.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.row.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form a.btn{font-size:.95em}.overlay{position:absolute;top:0;left:0;height:193%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.form-item.row.create-new:hover,.form-item.row:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.row.create-new:hover{background-color:#515151}.form-item.row>.title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item.row>.title-row h4{font-size:1.3em}.form-item.row.create-new>.title-row{padding:0}.form-item.row.create-new>.title-row h4{font-size:7em}.form-item.row>.details-row{margin-top:3.2em}.form-item.row>.details-row small{font-size:.6em}.form-item.row.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 ecd09f44..8651e138 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,2 +1,2 @@ -"use strict";var ApplicationConfiguration=function(){var applicationModuleName="medform",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||(event.preventDefault(),$state.go("home"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null===permissions||authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$state.go("access_denied")))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/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("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.form=form,!$scope.form.isLive&&$rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$scope.form.isLive?CurrentForm.setForm($scope.form):$state.go("access_denied"),console.log("$rootScope.hideNav: "+$rootScope.hideNav),console.log("$scope.form.isLive: "+$scope.form.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",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.viewSubmissions=!1,$rootScope.showCreateModal=!1,$scope.table={masterChecker:!1,rows:[]},$scope.findAll=function(){$scope.myforms||Forms.query(function(_forms){$scope.myforms=_forms})},$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.setForm=function(form){$scope.myform=form},$scope.openCreateModal=function(){$rootScope.showCreateModal||($rootScope.showCreateModal=!0)},$scope.closeCreateModal=function(){$rootScope.showCreateModal&&($rootScope.showCreateModal=!1)},$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(obj){obj.selected=!obj.selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();console.log(delete_ids),$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 i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected&&$scope.table.rows.splice(i,1)}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$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)})},$scope.createNew=function(){var form={};form.title=$scope.myform.name.$modelValue,form.language=$scope.myform.language.$modelValue,console.log(form),$rootScope.showCreateModal=!0,console.log($scope.myform),$scope.myform.$valid&&$scope.myform.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form created"),$scope.myform={},$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.update=$rootScope.update=function(cb){if(!$rootScope.saveInProgress&&$rootScope.finishedRender){$rootScope.saveInProgress=!0,console.log("begin updating form");var err=null;$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data,console.log(response.data),$scope.$digest||$scope.$apply()})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),console.log(response.data),err=response.data})["finally"](function(){console.log("finished updating"),$rootScope.saveInProgress=!1,cb(err)})}},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],link:function($scope,$element,$attrs,$ctrls){$rootScope.finishedRender=!1,void 0===$rootScope.watchCount&&($rootScope.watchCount=0);var difference=function(array){var rest=Array.prototype.concat.apply(Array.prototype,Array.prototype.slice.call(arguments,1)),containsEquals=function(obj,target){return null===obj?!1:_.any(obj,function(value){return _.isEqual(value,target)})};return _.filter(array,function(value){return!containsEquals(rest,value)})},$formCtrl=$ctrls[0],savePromise=null;$attrs.autoSaveForm||"true";$scope.$on("ngRepeatStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1,$rootScope.watchCount=0}),$scope.$on("ngRepeatFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.$watch("myform.form_fields",function(newValue,oldValue){console.log("watchCount: "+$rootScope.watchCount),0!==difference(oldValue,newValue).length&&void 0!==oldValue&&(!$rootScope.finishedRender||!$formCtrl.$dirty&&0===difference(oldValue,newValue).length||$rootScope.saveInProgress||($rootScope.watchCount++,savePromise&&$timeout.cancel(savePromise),savePromise=$timeout(function(){savePromise=null,$rootScope[$attrs.autoSaveCallback](function(err){err?(console.log("Error form data NOT persisted"),console.log(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$rootScope.watchCount=0,$formCtrl.$setPristine())})})))},!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{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)})}}},templateUrl:"./modules/forms/views/directiveViews/form/configure-form.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","timeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/edit-form.html",restrict:"E",scope:{myform:"=",user:"="},controller:function($scope){$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},console.log($scope.myform),$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.addNewField=function(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};$scope.myform.form_fields.unshift(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,field_index){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].field_id===field.field_id){$scope.addNewField($scope.myform.form_fields[i].fieldType);break}},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;ii;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",function($http,$compile){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"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});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,attr){scope.$first===!0&&$timeout(function(){$rootScope.$broadcast("ngRepeatStarted")}),scope.$last===!0&&(console.log(element),$timeout(function(){console.log("ngRepeatFinished"),$rootScope.$broadcast("ngRepeatFinished")}))}}}),angular.module("forms").directive("formDirective",["$http","$timeout","timeCounter","Auth",function($http,$timeout,timeCounter,Auth){return{controller:function($scope){timeCounter.startClock(),$scope.submit=function(){var _timeElapsed=timeCounter.stopClock();$scope.form.timeElapsed=_timeElapsed,$scope.authentication=Auth,console.log($scope.authentication.isAuthenticated()),$http.post("/forms/"+$scope.form._id,$scope.form).success(function(data,status,headers){console.log("form submitted successfully"),alert("Form submitted.."),$scope.form.submitted=!0}).error(function(error){console.log(error)})},$scope.reloadForm=function(){$scope.form.submitted=!1,$scope.form.form_fields=_.chain($scope.form.form_fields).map(function(field){return field.fieldValue="",field}).value()}},templateUrl:"./modules/forms/views/directiveViews/form/submit-form.html",restrict:"E",scope:{form:"="}}}]),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/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.createNew=function(){var form={};form.title=$scope.myform.name.$modelValue,form.language=$scope.myform.language.$modelValue,console.log(form),$rootScope.showCreateModal=!0,console.log($scope.myform),$scope.myform.$valid&&$scope.myform.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form created"),$scope.myform={},$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.remove=function(form_id){console.log("Remove existing form");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)})}}]),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.form=form,!$scope.form.isLive&&$rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$scope.form.isLive?CurrentForm.setForm($scope.form):$state.go("access_denied"),console.log("$rootScope.hideNav: "+$rootScope.hideNav),console.log("$scope.form.isLive: "+$scope.form.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(obj){obj.selected=!obj.selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();console.log(delete_ids),$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 i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected&&$scope.table.rows.splice(i,1)}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$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(cb){if(!$rootScope.saveInProgress&&$rootScope.finishedRender){$rootScope.saveInProgress=!0,console.log("begin updating form");var err=null;$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data,console.log(response.data),$scope.$digest||$scope.$apply()})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),console.log(response.data),err=response.data})["finally"](function(){console.log("finished updating"),$rootScope.saveInProgress=!1,cb(err)})}}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){$rootScope.finishedRender=!1;var $formCtrl=$scope.editForm,savePromise=null;$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&form[prop].$dirty&&form[prop].$untouched)return!0;return!1},$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){if(newValue||oldValue){var changedFields=!_.isEqual(oldValue,newValue);$scope.anyDirtyAndTouched($scope.editForm);$rootScope.finishedRender&&($formCtrl.$dirty||changedFields)&&!$rootScope.saveInProgress&&(console.log("Saving Form"),savePromise&&$timeout.cancel(savePromise),savePromise=$timeout(function(){savePromise=null,$rootScope[$attrs.autoSaveCallback](function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})}))}},!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("bnLifecycle",[function(){return{restrict:"A",link:function(scope,element,attributes){console.log("aoeuaoeu"),console.log("Linked:",attributes.id)}}}]).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){console.log("Linked: editForm Controller"),$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(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};$scope.myform.form_fields.unshift(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,field_index){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].field_id===field.field_id){$scope.addNewField($scope.myform.form_fields[i].fieldType);break}},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on"};$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",function($http,$compile){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","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){"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.$first&&!scope.$last?$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")}):scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})})}}}}),angular.module("forms").directive("formDirective",["$http","$timeout","timeCounter","Auth","$filter",function($http,$timeout,timeCounter,Auth,$filter){return{templateUrl:"./modules/forms/views/directiveViews/form/submit-form.html",restrict:"E",scope:{form:"="},controller:function($scope){console.log("rendering submitFormDirective"),timeCounter.startClock(),$scope.submit=function(){var _timeElapsed=timeCounter.stopClock();$scope.form.timeElapsed=_timeElapsed,$scope.form.percentageComplete=$filter("formValidity")($scope.form.visible_form_fields)/$scope.visible_form_fields.length,delete $scope.form.visible_form_fields,$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.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 diff --git a/public/modules/forms/controllers/view-form.client.controller.js b/public/modules/forms/controllers/view-form.client.controller.js index 50c3970f..989bcab5 100644 --- a/public/modules/forms/controllers/view-form.client.controller.js +++ b/public/modules/forms/controllers/view-form.client.controller.js @@ -197,28 +197,31 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope' // Update existing Form - $scope.update = $rootScope.update = function(cb) { - if(!$rootScope.saveInProgress && $rootScope.finishedRender){ - - $rootScope.saveInProgress = true; + $scope.update = $rootScope.update = function(immediate, cb) { + console.log('immediate: '+immediate); + var continueUpdate = true; + if(immediate){ + continueUpdate = !$rootScope.saveInProgress; + } + + if(continueUpdate){ console.log('begin updating form'); var err = null; + if(immediate){ $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); - if(!$scope.$digest){ - $scope.$apply(); - } }).catch(function(response){ console.log('Error occured during form UPDATE.\n'); console.log(response.data); err = response.data; }).finally(function() { console.log('finished updating'); - $rootScope.saveInProgress = false; - cb(err); + if(immediate){$rootScope.saveInProgress = false; } + cb(err); }); } }; diff --git a/public/modules/forms/css/form.css b/public/modules/forms/css/form.css index bd292400..08cf226f 100644 --- a/public/modules/forms/css/form.css +++ b/public/modules/forms/css/form.css @@ -161,7 +161,8 @@ div.config-form > .row { margin-bottom: 40px; } .admin-form > .page-header h1 { - margin-bottom: 0px + margin-bottom: 0px; + margin-top: 0px; } .admin-form > .page-header > .col-xs-3 { padding-top: 1.4em; diff --git a/public/modules/forms/directives/auto-save.client.directive.js b/public/modules/forms/directives/auto-save.client.directive.js index c71ae6da..f6a571ea 100644 --- a/public/modules/forms/directives/auto-save.client.directive.js +++ b/public/modules/forms/directives/auto-save.client.directive.js @@ -4,74 +4,56 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun return { require: ['^form'], + restrict: 'AE', + controller: function ($scope) { + + }, link: function($scope, $element, $attrs, $ctrls) { + angular.element(document).ready(function() { + + var $formCtrl = $ctrls[0], + savePromise = null; - $rootScope.finishedRender = false; - - var $formCtrl = $ctrls[0], - savePromise = null; - - - $scope.$on('editFormFieldsStarted', function(ngRepeatFinishedEvent) { $rootScope.finishedRender = false; - }); - $scope.$on('editFormFieldsFinished', function(ngRepeatFinishedEvent) { - $rootScope.finishedRender = true; - }); + $scope.$on('editFormFieldsStarted', function(ngRepeatFinishedEvent) { + $rootScope.finishedRender = false; + }); + $scope.$on('editFormFieldsFinished', function(ngRepeatFinishedEvent) { + $rootScope.finishedRender = true; + }); - // $scope.anyDirtyAndTouched = function (form){ - // console.log(form); - // console.log($scope.myform); - - - // for(var prop in form) { - // if(form.hasOwnProperty(prop) && prop[0] !== '$') { - // if(form[prop].$dirty && form[prop].$touched) { - // return true; - // } - // } - // } - // return false; - // }; - - // console.log($scope.watchModel); - $scope.$watch($attrs.autoSaveWatch, function(newValue, oldValue) { - console.log('hello'); - if( !newValue && !oldValue ){ - return; - } - var changedFields = !_.isEqual(oldValue,newValue); - - // console.log('\n\n----------'); - console.log('$dirty: '+( $formCtrl.$dirty ) ); - // console.log('oldValue: '+oldValue); - // console.log('newValue: '+newValue); - // console.log('form_fields changed: '+changedFields); - // console.log('$valid: '+$formCtrl.$valid); - // console.log('finishedRender: '+$rootScope.finishedRender); - // console.log('saveInProgress: '+$rootScope.saveInProgress); - - // var inputDirtyUntouched = $scope.anyDirtyAndTouched($scope.editForm); - - //Save form ONLY IF rendering is finished, form_fields have been change AND currently not save in progress - if($rootScope.finishedRender && (inputDirtyUntouched || changedFields) && !$rootScope.saveInProgress) { - - console.log('Saving Form'); - if(savePromise) { - $timeout.cancel(savePromise); + $scope.anyDirtyAndTouched = function(form){ + var propCount = 0; + for(var prop in form) { + if(form.hasOwnProperty(prop) && prop[0] !== '$') { + propCount++; + if(form[prop].$touched && form[prop].$dirty) { + return true; + } } + } + return false; + }; + var debounceUpdates = function () { + + // console.log('Saving Form'); + if(savePromise) { + $timeout.cancel(savePromise); + }else { savePromise = $timeout(function() { - savePromise = null; + $rootScope[$attrs.autoSaveCallback]( function(err){ if(!err){ - console.log('\n\nForm data persisted -- setting pristine flag'); + // console.log('\n\nForm data persisted -- setting pristine flag'); // console.log('\n\n---------\nUpdate form CLIENT'); // console.log(Date.now()); - $formCtrl.$setPristine(); - // $rootScope.saveInProgress = false; + $formCtrl.$setPristine(); + console.log($rootScope.saveInProgress); + savePromise = null; + // $formCtrl.$setUntouched(); }else{ console.error('Error form data NOT persisted'); console.error(err); @@ -79,14 +61,97 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun }); }); + } + }; + + // $scope.$watch('editForm', function(newValue, oldValue) { + // console.log('watch editForm'); + // if($scope.anyDirtyAndTouched($scope.editForm)){ + // console.log('ready to save text input'); + // } + // }); + + $scope.$watch(function(newValue, oldValue) { + // console.log('watch editForm'); + if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){ + console.log('ready to save text input'); + console.log('Saving Form'); + $rootScope.saveInProgress = true; + $rootScope[$attrs.autoSaveCallback](false, + 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'); + console.error(err); + } + }); + } + }); + + //Autosave Form when model (specificed in $attrs.autoSaveWatch) changes + $scope.$watch($attrs.autoSaveWatch, function(newValue, oldValue) { + + var changedFields = !_.isEqual(oldValue,newValue); + if( (!newValue && !oldValue) || !oldValue ){ + return; + } + + // console.log('\n\n----------'); + // console.log('$dirty: '+ $formCtrl.$dirty ); + // console.log('changedFields: '+changedFields); + // console.log('finishedRender: '+$rootScope.finishedRender); + // console.log('saveInProgress: '+$rootScope.saveInProgress); + // console.log('newValue: '+newValue); + // console.log('oldValue: '+oldValue); + + // var anyCurrentlyDirtyNotFocused = $scope.anyDirtyAndTouched($scope.editForm); + // console.log('anyCurrentlyDirtyNotFocused: '+anyCurrentlyDirtyNotFocused); + // console.log('properties of $scope.editForm'); + // for(var item in $scope.editForm){ + // console.log(item); // } - }else{ - return; - } - - }, true); + //Save form ONLY IF rendering is finished, form_fields have been change AND currently not save in progress + if($rootScope.finishedRender && (changedFields && !$formCtrl.$dirty) && !$rootScope.saveInProgress) { + + + if(savePromise) { + $timeout.cancel(savePromise); + savePromise = null; + } + + savePromise = $timeout(function() { + + console.log('Saving Form'); + $rootScope.saveInProgress = true; + $rootScope[$attrs.autoSaveCallback](false, + 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'); + console.error(err); + } + }); + }); + }else if($rootScope.finishedRender && $rootScope.saveInProgress){ + $rootScope.saveInProgress = false; + } + + }, true); + + + + }); + } }; -}]); \ No newline at end of file +}]); diff --git a/public/modules/forms/directives/edit-form.client.directive.js b/public/modules/forms/directives/edit-form.client.directive.js index e35dce3c..5ee4926b 100644 --- a/public/modules/forms/directives/edit-form.client.directive.js +++ b/public/modules/forms/directives/edit-form.client.directive.js @@ -1,6 +1,7 @@ 'use strict'; -angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields', +angular.module('forms') +.directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields', function ($rootScope, $q, $http, $timeout, timeCounter, Auth, FormFields) { return { templateUrl: './modules/forms/views/directiveViews/form/edit-form.html', @@ -8,8 +9,28 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht scope: { myform:'=', }, - transclude: true, + // transclude: true, controller: function($scope){ + + // Log that the directive has been linked. + // console.log( "Linked: editForm Controller"); + + /* + ** 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; @@ -67,19 +88,9 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht // }; - //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; - + /* + ** Field CRUD Methods + */ // Add a new field $scope.addNewField = function(fieldType){ @@ -105,7 +116,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht }; // put newField into fields array - $scope.myform.form_fields.unshift(newField); + $scope.myform.form_fields.push(newField); // console.log('\n\n---------\nAdded field CLIENT'); // console.log(Date.now()); // console.log($scope.myform.form_fields.length); @@ -131,6 +142,10 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht } }; + /* + ** Field Option Methods + */ + // add new option to the field $scope.addOption = function (field){ if(!field.fieldOptions) field.fieldOptions = []; diff --git a/public/modules/forms/directives/on-finish-render.client.directive.js b/public/modules/forms/directives/on-finish-render.client.directive.js index 3c99ab6b..434c1654 100644 --- a/public/modules/forms/directives/on-finish-render.client.directive.js +++ b/public/modules/forms/directives/on-finish-render.client.directive.js @@ -12,8 +12,7 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; - - if(scope.$first && !scope.$last) { + if(!scope.$last) { $timeout(function () { // console.log(broadcastMessage+'Started'); $rootScope.$broadcast(broadcastMessage+'Started'); diff --git a/public/modules/forms/views/directiveViews/cgBusy/updateFormLoading.html b/public/modules/forms/views/directiveViews/cgBusy/updateFormLoading.html new file mode 100644 index 00000000..86de2d0b --- /dev/null +++ b/public/modules/forms/views/directiveViews/cgBusy/updateFormLoading.html @@ -0,0 +1,3 @@ +
+
{{$message}}
+
\ No newline at end of file diff --git a/public/modules/forms/views/directiveViews/form/configure-form.html b/public/modules/forms/views/directiveViews/form/configure-form.html index ee76daae..95560129 100644 --- a/public/modules/forms/views/directiveViews/form/configure-form.html +++ b/public/modules/forms/views/directiveViews/form/configure-form.html @@ -183,7 +183,7 @@
- +
\ No newline at end of file diff --git a/public/modules/forms/views/directiveViews/form/edit-form.html b/public/modules/forms/views/directiveViews/form/edit-form.html index b55e4269..a42f77c6 100644 --- a/public/modules/forms/views/directiveViews/form/edit-form.html +++ b/public/modules/forms/views/directiveViews/form/edit-form.html @@ -1,170 +1,182 @@ -
-
- -
-

Add New Field

-
-
-
-
-
- - - - - {{type.value}} + + +
+ +
+

Add New Field

+
+
+
+
+
+ + + + + {{type.value}} +
-
-
-
-
- +
+
+
+ - + - + -
+
- - - - {{field.title}} - - - - - - -
- -
-
-
-

Preview

+ + + + {{field.title}} + + + + + +
-
-
-
    - - -
-
+ +
-
-
-
-

Edit

-
-
-
- - -
-
Question Title:
-
-
-
-
-
-
Description:
-
-
- -

-
-
Options:
-
-
- - - - - - - Value: {{ option.option_value }} - +
+
+

Preview Field

+
+
    + + +
+
+ +
+
+
+

Edit Field

+
+
+
+ +
+
Question Title:
+
+
+
+ +

+ +
+
Description:
+
+
+ +

+
+
Options:
+
+
+ + + + + + + Value: {{ option.option_value }} + +
+ +
+
+ +

+ +
+
Required:
+
+ + + +
+
+ +
+
Disabled:
+
+ + + +
+
+ +


+ +
+
+
-
+ -

- -
-
Required:
-
- - - -
+
+
+

+ Drag and Drop new fields here +

-
-
-
Disabled:
-
- - - -
-
- -
-
-

- Drag and Drop new fields here -

-
-
- - -
-
-
-
-
- - - + +
+
+
+
+
+ + + +
-
-
-
-
-
- - - +
+
+
+
+ + + +
-
- \ No newline at end of file + + diff --git a/public/modules/forms/views/view-form.client.view.html b/public/modules/forms/views/view-form.client.view.html index 8f5f910c..30a7a351 100644 --- a/public/modules/forms/views/view-form.client.view.html +++ b/public/modules/forms/views/view-form.client.view.html @@ -23,10 +23,10 @@