got ListFormsController tests to pass

This commit is contained in:
David Baldwynn 2015-08-20 11:47:25 -07:00
parent 0f21478c46
commit 1fb36f9b4e
12 changed files with 837 additions and 203 deletions

View file

@ -47,55 +47,55 @@ angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_RO
superuser: 'superuser',
});
angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams',
function($rootScope, Auth, $state, $stateParams) {
// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams',
// function($rootScope, Auth, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
// $rootScope.$state = $state;
// $rootScope.$stateParams = $stateParams;
// add previous state property
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
$state.previous = fromState;
// // add previous state property
// $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
// $state.previous = fromState;
//Redirect to listForms if user is authenticated
if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){
if(Auth.isAuthenticated()){
event.preventDefault(); // stop current execution
$state.go('listForms'); // go to listForms page
}
}
//Redirect to 'home' route if user is not authenticated
else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){
event.preventDefault(); // stop current execution
$state.go('home'); // go to listForms page
}
// //Redirect to listForms if user is authenticated
// if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){
// if(Auth.isAuthenticated()){
// event.preventDefault(); // stop current execution
// $state.go('listForms'); // go to listForms page
// }
// }
// //Redirect to 'home' route if user is not authenticated
// else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){
// event.preventDefault(); // stop current execution
// $state.go('home'); // go to listForms page
// }
});
// });
}
]);
// }
// ]);
//Page access/authorization logic
angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams',
function($rootScope, Auth, User, Authorizer, $state, $stateParams) {
$rootScope.$on('$stateChangeStart', function(event, next) {
var authenticator, permissions, user;
permissions = next && next.data && next.data.permissions ? next.data.permissions : null;
// //Page access/authorization logic
// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams',
// function($rootScope, Auth, User, Authorizer, $state, $stateParams) {
// $rootScope.$on('$stateChangeStart', function(event, next) {
// var authenticator, permissions, user;
// permissions = next && next.data && next.data.permissions ? next.data.permissions : null;
Auth.ensureHasCurrentUser(User);
user = Auth.currentUser;
// Auth.ensureHasCurrentUser(User);
// user = Auth.currentUser;
if(user){
authenticator = new Authorizer(user);
// if(user){
// authenticator = new Authorizer(user);
if( (permissions !== null) && !authenticator.canAccess(permissions) ){
event.preventDefault();
console.log('access denied')
$state.go('access_denied');
}
}
});
}]);
// if( (permissions !== null) && !authenticator.canAccess(permissions) ){
// event.preventDefault();
// console.log('access denied')
// $state.go('access_denied');
// }
// }
// });
// }]);
//Then define the init function for starting up the application
angular.element(document).ready(function() {
@ -442,21 +442,19 @@ angular.module('forms').config(['$stateProvider',
angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$modal',
function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http, $modal) {
var deleteModal;
$scope = $rootScope;
$scope.myform = CurrentForm.getForm();
$rootScope.saveInProgress = false;
// Find a specific Form
$scope.findOne = function() {
$scope.findOne = function(){
$scope.myform = Forms.get({
formId: $stateParams.formId
});
CurrentForm.setForm($scope.myform);
};
$scope.setForm = function (form) {
$scope.setForm = function(form){
$scope.myform = form;
};
$rootScope.resetForm = function(){
@ -468,83 +466,71 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope
/*
** DeleteModal Functions
*/
$scope.openDeleteModal = function() {
deleteModal = $modal.open({
$scope.openDeleteModal = function(){
$scope.deleteModal = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'AdminFormController',
});
};
$scope.cancelDeleteModal = function(){
if(deleteModal){
deleteModal.dismiss('cancel');
if($scope.deleteModal){
$scope.deleteModal.dismiss('cancel');
}
};
// Remove existing Form
$scope.remove = function(form_id) {
if(deleteModal && deleteModal.opened){
$scope.removeCurrentForm = function() {
if($scope.deleteModal && $scope.deleteModal.opened){
deleteModal.close();
$scope.deleteModal.close();
var form = {};
if(!form_id){
form = CurrentForm.getForm();
if(!form) form = $scope.myform;
}else {
form._id = form_id;
}
var form_id = $scope.myform._id;
if(!form_id) throw new Error('Error - removeCurrentForm(): $scope.myform._id does not exist');
$http.delete('/forms/'+form._id)
$http.delete('/forms/'+form_id)
.success(function(data, status, headers){
console.log('form deleted successfully');
if(!form_id){
$state.go('listForms', {}, {reload: true});
}
if($scope.myforms.length > 0){
$scope.myforms = _.filter($scope.myforms, function(myform){
return myform._id !== form._id;
});
}
$state.go('listForms', {}, {reload: true});
}).error(function(error){
console.log('ERROR: Form could not be deleted.');
console.error(error);
}).finally(function(){
});
}
};
// Update existing Form
$scope.update = $rootScope.update = function(immediate, cb) {
// console.log('immediate: '+immediate);
$scope.update = $rootScope.update = function(updateImmediately, cb){
var continueUpdate = true;
if(immediate){
continueUpdate = !$rootScope.saveInProgress;
if(!updateImmediately){
continueUpdate = !$rootScope.saveInProgress;
}
//Update form if we **are not currently updating** or if **shouldUpdateNow flag is set**
if(continueUpdate){
console.log('begin updating form');
// console.log('begin updating form');
var err = null;
if(immediate){ $rootScope.saveInProgress = true; }
if(!updateImmediately){ $rootScope.saveInProgress = true; }
$scope.updatePromise = $http.put('/forms/'+$scope.myform._id, {form: $scope.myform})
.then(function(response){
$rootScope.myform = $scope.myform = response.data;
console.log(response.data);
// console.log(response.data);
}).catch(function(response){
console.log('Error occured during form UPDATE.\n');
console.log(response.data);
// console.log('Error occured during form UPDATE.\n');
// console.log(response.data);
err = response.data;
}).finally(function() {
console.log('finished updating');
if(immediate){$rootScope.saveInProgress = false; }
cb(err);
// console.log('finished updating');
if(!updateImmediately){$rootScope.saveInProgress = false; }
if( (typeof cb) === 'function'){
cb(err);
}
});
}
};
@ -554,11 +540,12 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope
'use strict';
// Forms controller
angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm','$http',
angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http',
function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) {
$scope = $rootScope;
$rootScope.showCreateModal = false;
$scope.forms = {};
$scope.showCreateModal = false;
// Return all user's Forms
$scope.findAll = function() {
@ -569,13 +556,13 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
//Modal functions
$scope.openCreateModal = function(){
if(!$rootScope.showCreateModal){
$rootScope.showCreateModal = true;
if(!$scope.showCreateModal){
$scope.showCreateModal = true;
}
};
$scope.closeCreateModal = function(){
if($rootScope.showCreateModal){
$rootScope.showCreateModal = false;
if($scope.showCreateModal){
$scope.showCreateModal = false;
}
};
@ -586,13 +573,14 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
$state.go(route, {'formId': id}, {reload: true});
};
$scope.duplicate = function(form, form_index){
$scope.duplicate = function(form_index){
var form = $scope.myforms[form_index];
delete form._id;
$http.post('/forms', {form: form})
.success(function(data, status, headers){
console.log('form duplicated');
$scope.myforms.splice(form_index, 0, data);
// console.log('form duplicated');
$scope.myforms.splice(form_index+1, 0, data);
}).error(function(errorResponse){
console.log(errorResponse);
$scope.error = errorResponse.data.message;
@ -601,40 +589,36 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
// Create new Form
$scope.createNew = function(){
var form = {};
form.title = $scope.myform.name.$modelValue;
form.language = $scope.myform.language.$modelValue;
// console.log(form);
$rootScope.showCreateModal = true;
console.log($scope.forms.createForm);
// console.log($scope.myform);
if($scope.myform.$valid && $scope.myform.$dirty){
var form = {};
form.title = $scope.forms.createForm.$modelValue;
form.language = $scope.forms.createForm.language.$modelValue;
if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){
$http.post('/forms', {form: form})
.success(function(data, status, headers){
console.log('form created');
console.log('new form created');
// Redirect after save
$scope.goToWithId('viewForm', data._id+'');
}).error(function(errorResponse){
console.log(errorResponse);
console.error(errorResponse);
$scope.error = errorResponse.data.message;
});
}
};
$scope.removeFromList = function(deleted_form_id) {
$scope.removeForm = function(form_index) {
if(form_index >= $scope.myforms.length || form_index < 0){
throw new Error('Error: form_index in removeForm() must be between 0 and '+$scope.myforms.length-1);
}
console.log('Remove existing form');
$http.delete('/forms/'+deleted_form_id)
$http.delete('/forms/'+$scope.myforms[form_index]._id)
.success(function(data, status, headers){
console.log('form deleted successfully');
if($scope.myforms.length > 0){
$scope.myforms = _.filter($scope.myforms, function(myform){
return myform._id !== deleted_form_id;
});
}
$scope.myforms.splice(form_index, 1);
}).error(function(error){
console.log('ERROR: Form could not be deleted.');
@ -714,12 +698,10 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
var debounceSave = function () {
$rootScope.saveInProgress = true;
$rootScope[$attrs.autoSaveCallback](false,
$rootScope[$attrs.autoSaveCallback](true,
function(err){
if(!err){
console.log('\n\nForm data persisted -- setting pristine flag');
// console.log('\n\n---------\nUpdate form CLIENT');
// console.log(Date.now());
$formCtrl.$setPristine();
}else{
console.error('Error form data NOT persisted');
@ -728,7 +710,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
});
};
//Update/save Form if any Form fields are Dirty and Touched
$scope.$watch(function(newValue, oldValue) {
if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){
debounceSave();
@ -763,7 +745,9 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
console.log('Saving Form');
debounceSave();
});
}else if($rootScope.finishedRender && $rootScope.saveInProgress){
}
//If we are finished rendering then form saving should be finished
else if($rootScope.finishedRender && $rootScope.saveInProgress){
$rootScope.saveInProgress = false;
}
@ -816,6 +800,324 @@ angular.module('forms').directive('changeFocus', function() {
});
'use strict';
angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields',
function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) {
return {
templateUrl: './modules/forms/views/directiveViews/form/configure-form.client.view.html',
restrict: 'E',
scope: {
myform:'=',
user:'=',
pdfFields:'@',
formFields:'@'
},
controller: function($scope){
$scope.log = '';
$scope.pdfLoading = false;
$scope.languages = $rootScope.languages;
var _current_upload = null;
$scope.resetForm = $rootScope.resetForm;
$scope.update = $rootScope.update;
var _unbindedPdfFields = $scope.pdfFields;
//DAVID: TODO: finish this so we can create a Form.pdfFieldMap
// $scope.getUnbindedPdfFields = function(fieldType){
// _unbindedPdfFields = $scope.pdfFields
// }
//PDF Functions
$scope.cancelUpload = function(){
_current_upload.abort();
$scope.pdfLoading = false;
$scope.removePDF();
};
$scope.removePDF = function(){
$scope.myform.pdf = null;
$scope.myform.isGenerated = false;
$scope.myform.autofillPDFs = false;
console.log('form.pdf: '+$scope.myform.pdf+' REMOVED');
};
$scope.uploadPDF = function(files) {
if (files && files.length) {
// for (var i = 0; i < files.length; i++) {
var file = files[0];
console.log(file);
_current_upload = Upload.upload({
url: '/upload/pdf',
fields: {
'user': $scope.user,
'form': $scope.myform
},
file: file
}).progress(function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
$scope.log = 'progress: ' + progressPercentage + '% ' +
evt.config.file.name + '\n' + $scope.log;
$scope.pdfLoading = true;
}).success(function (data, status, headers, config) {
$scope.log = 'file ' + data.originalname + ' uploaded as '+ data.name +'. JSON: ' + JSON.stringify(data) + '\n' + $scope.log;
$scope.myform.pdf = angular.fromJson(angular.toJson(data));
console.log($scope.myform.pdf);
$scope.pdfLoading = false;
console.log($scope.log);
if(!$scope.$$phase && !$scope.$digest){
$scope.$apply();
}
}).error(function(err){
$scope.pdfLoading = false;
console.log('Error occured during upload.\n');
console.log(err);
});
}
};
}
};
}
]);
'use strict';
angular.module('forms')
.directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields',
function ($rootScope, $q, $http, $timeout, timeCounter, Auth, FormFields) {
return {
templateUrl: './modules/forms/views/directiveViews/form/edit-form.client.view.html',
restrict: 'E',
scope: {
myform:'=',
},
// transclude: true,
controller: function($scope){
/*
** Initialize scope with variables
*/
//Populate AddField with all available form field types
$scope.addField = {};
$scope.addField.types = FormFields.fields;
$scope.addField.types.forEach(function(type){
type.lastAddedID = 1;
return type;
});
// Accordion settings
$scope.accordion = {};
$scope.accordion.oneAtATime = true;
//Populate local scope with rootScope methods/variables
$scope.update = $rootScope.update;
/*
** FormFields (ui-sortable) drag-and-drop configuration
*/
$scope.dropzone = {
handle: ' .handle'
};
// $scope.draggable = {
// connectWith: ".dropzone",
// start: function (e, ui) {
// // $scope.$apply(function() {
// // $scope.dragging = true
// // });
// $('.dropzone').sortable('refresh');
// },
// update: function (e, ui) {
// var isInDropzone = $(e.target).parentsUntil('.panel-group').hasClass('dropzone');
// console.log('isInDropzone: '+isInDropzone);
// //Disable drag and drop if we aren't in dropzone
// if(!isInDropzone){
// ui.item.sortable.cancel();
// }
// },
// stop: function (e, ui) {
// var isInDropzone = $(e.target).parentsUntil('.panel-group').hasClass('dropzone');
// //Disable drag and drop if we aren't in dropzone
// if(isInDropzone){
// console.log($(e.target));
// }
// // if (ui.item.sortable.droptarget === undefined) {
// // $scope.$apply($scope.dragging = false);
// // return;
// // }else if (ui.item.sortable.droptarget[0].classList[0] === "dropzone") {
// // // run code when item is dropped in the dropzone
// // $scope.$apply($scope.dragging = false);
// // }else{
// // // $scope.$apply($scope.dragging = false);
// // }
// // console.log('has class .dropzone :'+);
// // if ($(e.target).hasClass('dropzone') && ui.item.sortable.droptarget && e.target != ui.item.sortable.droptarget[0] ) {
// // // restore original types
// // $scope.addField.types = FormFields.fields;
// // }
// }
// };
/*
** Field CRUD Methods
*/
// Add a new field
$scope.addNewField = function(addOrReturn, fieldType){
// incr field_id counter
$scope.addField.lastAddedID++;
var fieldTitle;
for(var i = 0; i < $scope.addField.types.length; i++){
// console.log($scope.addField.types[i].name === fieldType);
if($scope.addField.types[i].name === fieldType){
$scope.addField.types[i].lastAddedID++;
// console.log($scope.addField.types[i].lastAddedID);
fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;
break;
}
}
var newField = {
'title' : fieldTitle,
'fieldType' : fieldType,
'fieldValue' : '',
'required' : true,
'disabled' : false,
};
console.log('\n\n---------\nAdded field CLIENT');
console.log(newField);
// put newField into fields array
if(addOrReturn){
$scope.myform.form_fields.push(newField);
}else {
return newField;
}
// console.log(Date.now());
// console.log($scope.myform.form_fields.length);
};
// deletes particular field on button click
$scope.deleteField = function (hashKey){
// console.log($scope.myform.form_fields);
for(var i = 0; i < $scope.myform.form_fields.length; i++){
// console.log($scope.myform.form_fields[i].$$hashKey === hashKey);
if($scope.myform.form_fields[i].$$hashKey === hashKey){
$scope.myform.form_fields.splice(i, 1);
break;
}
}
};
$scope.duplicateField = function (field_index){
console.log('field_index: '+field_index);
var field = $scope.addNewField(false, $scope.myform.form_fields[field_index].fieldType);
field.title = $scope.myform.form_fields[field_index].title;
console.log($scope.myform.form_fields[field_index]);
//Insert field at selected index
$scope.myform.form_fields.splice(field_index+1, 0, field);
};
/*
** startPage Button Methods
*/
// add new Button to the startPage/EndPage
$scope.addButton = function (newButtons){
var newButton = {};
newButton.bgColor = '#ddd';
newButton.color = '#ffffff';
newButton.text = 'Button';
$scope.myform.startPage.buttons.push(newButton);
};
// delete particular Button
$scope.deleteButton = function(button){
var hashKey = _.chain(button.$$hashKey).words().last().parseInt().value();
for(var i = 0; i < $scope.myform.startPage.buttons.length; i++){
var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();;
if(currHashKey === hashKey){
$scope.myform.startPage.buttons.splice(i, 1);
break;
}
}
};
/*
** Field Option Methods
*/
// add new option to the field
$scope.addOption = function (field){
if(!field.fieldOptions) field.fieldOptions = [];
var lastOptionID = 0;
if(field.fieldOptions[field.fieldOptions.length-1])
lastOptionID = field.fieldOptions[field.fieldOptions.length-1].option_id;
// new option's id
var option_id = lastOptionID + 1;
var newOption = {
'option_id' : option_id,
'option_title' : 'Option ' + option_id,
'option_value' : option_id
};
// put new option into fieldOptions array
field.fieldOptions.push(newOption);
};
// delete particular option
$scope.deleteOption = function (field, option){
for(var i = 0; i < field.fieldOptions.length; i++){
if(field.fieldOptions[i].option_id === option.option_id){
field.fieldOptions.splice(i, 1);
break;
}
}
};
// decides whether field options block will be shown (true for dropdown and radio fields)
$scope.showAddOptions = function (field){
if(field.fieldType === 'dropdown' || field.fieldType === 'checkbox' || field.fieldType === 'radio'){
return true;
} else {
return false;
}
};
},
};
}
]);
'use strict';
angular.module('forms').directive('fieldIconDirective', function($http, $compile) {
return {
@ -962,6 +1264,159 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo
'use strict';
angular.module('forms').directive('submissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields',
function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) {
return {
templateUrl: './modules/forms/views/directiveViews/form/submissions-form.client.view.html',
restrict: 'E',
scope: {
myform:'=',
user:'='
},
controller: function($scope){
$scope.table = {
masterChecker: false,
rows: []
};
/*
** Table Functions
*/
$scope.isAtLeastOneChecked = function(){
// console.log('isAtLeastOneChecked');
for(var i=0; i<$scope.table.rows.length; i++){
if($scope.table.rows[i].selected) return true;
}
return false;
};
$scope.toggleAllCheckers = function(){
// console.log('toggleAllCheckers');
for(var i=0; i<$scope.table.rows.length; i++){
$scope.table.rows[i].selected = $scope.table.masterChecker;
}
};
$scope.toggleObjSelection = function($event, description) {
$event.stopPropagation();
};
$scope.rowClicked = function(row_index) {
$scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected;
};
/*
* Form Submission Methods
*/
//Delete selected submissions of Form
$scope.deleteSelectedSubmissions = function(){
// console.log('deleteSelectedSubmissions');
var delete_ids = _.chain($scope.table.rows).filter(function(row){
return !!row.selected;
}).pluck('_id').value();
$http({ url: '/forms/'+$scope.myform._id+'/submissions',
method: 'DELETE',
data: {deleted_submissions: delete_ids},
headers: {'Content-Type': 'application/json;charset=utf-8'}
}).success(function(data, status, headers){
//Remove deleted ids from table
var tmpArray = [];
for(var i=0; i<$scope.table.rows.length; i++){
if(!$scope.table.rows[i].selected){
tmpArray.push($scope.table.rows[i]);
}
}
console.log(tmpArray);
$scope.table.rows = tmpArray;
})
.error(function(err){
console.log('Could not delete form submissions.\nError: ');
console.log(err);
console.error = err;
});
};
//Export selected submissions of Form
$scope.exportSubmissions = function(type){
var fileMIMETypeMap = {
'xls': 'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'json': 'json',
'csv': 'csv',
};
var blob = new Blob([document.getElementById('table-submission-data').innerHTM], {
type: 'application/'+fileMIMETypeMap[type]+';charset=utf-8'
});
saveAs(blob, $scope.myform.title+'_sumbissions_export_'+Date.now()+'.'+type);
};
//Fetch and display submissions of Form
$scope.showSubmissions = function(){
$http.get('/forms/'+$scope.myform._id+'/submissions')
.success(function(data, status, headers){
var _data = [],
_currentSubmission,
_tmpSubFormFields,
defaultFormFields = JSON.parse(JSON.stringify($scope.myform.form_fields));
//Iterate through form's submissions
for(var i=0; i<data.length; i++){
// _tmpSubFormFields = defaultFormFields;
_tmpSubFormFields = _.merge(defaultFormFields, data[i].form_fields);
_data[i].form_fields = _tmpSubFormFields;
// currentSubmission = data[i];
// for(var x=0; x<defaultFormFields.length; x++){
// var currField__id = defaultFormFields[x]._id,
// currField;
// _.find(currentSubmission.form_fields, function(fieldItem, fieldIdx){
// if(fieldItem._id === currField__id){
// currField = fieldItem;
// return true;
// }
// });
// if( (typeof currField) !== 'undefined'){
// _tmpSubFormFields[x].fieldValue = currField.fieldValue;
// _tmpSubFormFields[x].$$hashKey = currField.$$hashKey;
// }else {
// _tmpSubFormFields[x].fieldValue = '';
// }
// }
// _data[i] = currentSubmission;
// _data[i].form_fields = _tmpSubFormFields;
}
// console.log(JSON.stringify(_data));
$scope.submissions = _data;
$scope.table.rows = _data;
if(!$scope.$$phase && !$scope.$digest){
$scope.$apply();
}
// console.log('form submissions successfully fetched');
// console.log( JSON.parse(JSON.stringify($scope.submissions)) ) ;
// console.log( JSON.parse(JSON.stringify($scope.myform.form_fields)) );
})
.error(function(err){
console.error('Could not fetch form submissions.\nError: '+err);
});
};
}
};
}
]);
'use strict';
angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', '$filter', '$rootScope',
function ($http, $timeout, timeCounter, Auth, $filter, $rootScope) {
return {
@ -1010,7 +1465,7 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
};
$scope.exitStartPage = function () {
$scope.exitstartPage = function () {
$scope.form.startPage.showStart = false;
};
@ -1066,8 +1521,8 @@ angular.module('forms').directive('tableDirective', ['$http', '$timeout', 'Auth'
'use strict';
//Forms service used for communicating with the forms REST endpoints
angular.module('forms').service('CurrentForm', ['Forms',
function(Forms){
angular.module('forms').service('CurrentForm',
function(){
//Private variables
var _form = {};
@ -1080,7 +1535,7 @@ angular.module('forms').service('CurrentForm', ['Forms',
_form = form;
};
}
]);
);
'use strict';
angular.module('forms').service('FormFields', [
@ -1167,21 +1622,22 @@ angular.module('forms').service('FormFields', [
//Forms service used for communicating with the forms REST endpoints
angular.module('forms').factory('Forms', ['$resource',
function($resource) {
return $resource('forms/:formId', {
return $resource('/forms/:formId', {
formId: '@_id'
}, {
'query' : {
method: 'GET',
isArray: true,
transformResponse: function(data, header) {
var forms = angular.fromJson(data);
angular.forEach(forms, function(form, idx) {
form.visible_form_fields = _.filter(form.form_fields, function(field){
return field.deletePreserved === false;
}); //<-- replace each item with an instance of the resource object
});
return forms;
}
//DAVID: TODO: Do we really need to get visible_form_fields for a Query?
// transformResponse: function(data, header) {
// var forms = angular.fromJson(data);
// angular.forEach(forms, function(form, idx) {
// form.visible_form_fields = _.filter(form.form_fields, function(field){
// return (field.deletePreserved === false);
// });
// });
// return forms;
// }
},
'get' : {
method: 'GET',
@ -1189,8 +1645,8 @@ angular.module('forms').factory('Forms', ['$resource',
var form = angular.fromJson(data);
form.visible_form_fields = _.filter(form.form_fields, function(field){
return field.deletePreserved === false;
}); //<-- replace each item with an instance of the resource object
return (field.deletePreserved === false);
});
return form;
}
},
@ -1710,7 +2166,6 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
$http.post('/auth/signin', credentials).success(function(response) {
deferred.resolve(response);
}).error(function(error) {
deferred.reject(error.message || error);
});
return deferred.promise;
@ -1765,7 +2220,6 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
resetPassword: function(passwordDetails, token) {
var deferred = $q.defer();
$http.get('/auth/password/'+token, passwordDetails).success(function(response) {
deferred.resolve();
}).error(function(error) {
deferred.reject(error.message || error);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -52,10 +52,10 @@
display: none !important;
}
.ng-invalid.ng-dirty {
border-color: #FA787E;
/*border-color: #FA787E;*/
}
.ng-valid.ng-dirty {
border-color: #78FA89;
/*border-color: #78FA89;*/
}
.browsehappy.jumbotron.hide,
body.ng-cloak

View file

@ -0,0 +1,128 @@
/* Container used for styling the custom select, the buttom class below adds the bg gradient, corners, etc. */
.custom-select {
position: relative;
display:block;
padding:0;
}
/* This is the native select, we're making everything but the text invisible so we can see the button styles in the wrapper */
.custom-select select {
width:100%;
margin:0;
background:none;
border: 1px solid transparent;
border-radius: 0px;
outline: none;
/* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/* Remove select styling */
appearance: none;
-webkit-appearance: none;
/* Font size must the 16px or larger to prevent iOS page zoom on focus */
font-size:1em;
/* General select styles: change as needed */
font-family: helvetica, sans-serif;
font-weight: bold;
color: #444;
padding: .6em 1.9em .5em .8em;
line-height:1.3;
}
/* Custom arrow sits on top of the select - could be an image, SVG, icon font, etc. or the arrow could just baked into the bg image on the select. Note this si a 2x image so it will look bad in browsers that don't support background-size. In production, you'd handle this resolution switch via media query but this is a demo. */
.custom-select::after {
content: "";
position: absolute;
width: 9px;
height: 8px;
top: 50%;
right: 1em;
margin-top:-4px;
background-image: url(http://filamentgroup.com/files/select-arrow.png);
background-repeat: no-repeat;
background-size: 100%;
z-index: 2;
/* This hack make the select behind the arrow clickable in some browsers */
pointer-events:none;
}
/* Hover style */
.custom-select:hover {
border:1px solid #888;
}
/* Focus style */
.custom-select select:focus {
outline:none;
box-shadow: 0 0 1px 3px rgba(180,222,250, 1);
background-color:transparent;
color: #222;
border:1px solid #aaa;
}
/* Set options to normal weight */
.custom-select option {
font-weight:normal;
}
/* ------------------------------------ */
/* START OF UGLY BROWSER-SPECIFIC HACKS */
/* ---------------------------------- */
/* OPERA - Pre-Blink nix the custom arrow, go with a native select button to keep it simple. Targeted via this hack http://browserhacks.com/#hack-a3f166304aafed524566bc6814e1d5c7 */
x:-o-prefocus, .custom-select::after {
display:none;
}
/* IE 10/11+ - This hides native dropdown button arrow so it will have the custom appearance, IE 9 and earlier get a native select - targeting media query hack via http://browserhacks.com/#hack-28f493d247a12ab654f6c3637f6978d5 - looking for better ways to achieve this targeting */
/* The second rule removes the odd blue bg color behind the text in the select button in IE 10/11 and sets the text color to match the focus style's - fix via http://stackoverflow.com/questions/17553300/change-ie-background-color-on-unopened-focused-select-box */
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.custom-select select::-ms-expand {
display: none;
}
.custom-select select:focus::-ms-value {
background: transparent;
color: #222;
}
}
/* FIREFOX won't let us hide the native select arrow, so we have to make it wider than needed and clip it via overflow on the parent container. The percentage width is a fallback since FF 4+ supports calc() so we can just add a fixed amount of extra width to push the native arrow out of view. We're applying this hack across all FF versions because all the previous hacks were too fragile and complex. You might want to consider not using this hack and using the native select arrow in FF. Note this makes the menus wider than the select button because they display at the specified width and aren't clipped. Targeting hack via http://browserhacks.com/#hack-758bff81c5c32351b02e10480b5ed48e */
/* Show only the native arrow */
@-moz-document url-prefix() {
.custom-select {
overflow: hidden;
}
.custom-select select {
width: 120%;
width: -moz-calc(100% + 3em);
width: calc(100% + em);
}
}
/* Firefox focus has odd artifacts around the text, this kills that. See https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-focusring */
.custom-select select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
/* ------------------------------------ */
/* END OF UGLY BROWSER-SPECIFIC HACKS */
/* ------------------------------------ */

View file

@ -5,7 +5,8 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) {
$scope = $rootScope;
$rootScope.showCreateModal = false;
$scope.forms = {};
$scope.showCreateModal = false;
// Return all user's Forms
$scope.findAll = function() {
@ -16,13 +17,13 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
//Modal functions
$scope.openCreateModal = function(){
if(!$rootScope.showCreateModal){
$rootScope.showCreateModal = true;
if(!$scope.showCreateModal){
$scope.showCreateModal = true;
}
};
$scope.closeCreateModal = function(){
if($rootScope.showCreateModal){
$rootScope.showCreateModal = false;
if($scope.showCreateModal){
$scope.showCreateModal = false;
}
};
@ -34,13 +35,14 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
};
$scope.duplicate = function(form_index){
var form = $scope.myforms[form_index];
delete form._id;
var form = _.clone($scope.myforms[form_index]);
form._id = '';
$http.post('/forms', {form: form})
.success(function(data, status, headers){
// console.log('form duplicated');
console.log('form duplicated');
$scope.myforms.splice(form_index+1, 0, data);
console.log($scope.myforms[3]._id);
}).error(function(errorResponse){
console.log(errorResponse);
$scope.error = errorResponse.data.message;
@ -49,22 +51,21 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
// Create new Form
$scope.createNew = function(){
var form = {};
form.title = $scope.myform.name.$modelValue;
form.language = $scope.myform.language.$modelValue;
// console.log(form);
$rootScope.showCreateModal = true;
console.log($scope.forms.createForm);
// console.log($scope.myform);
if($scope.myform.$valid && $scope.myform.$dirty){
var form = {};
form.title = $scope.forms.createForm.title.$modelValue;
form.language = $scope.forms.createForm.language.$modelValue;
if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){
$http.post('/forms', {form: form})
.success(function(data, status, headers){
console.log('form created');
console.log('new form created');
// Redirect after save
$scope.goToWithId('viewForm', data._id+'');
}).error(function(errorResponse){
console.log(errorResponse);
console.error(errorResponse);
$scope.error = errorResponse.data.message;
});
}

View file

@ -1,8 +1,6 @@
.panel-default.startPage {
/*background-color: #eee;*/
border-style: dashed;
border-color: #a9a9a9;
border-color: #a9a9a9;
border-width:3px;
}
@ -11,7 +9,7 @@ section.content p {
}
.btn {
border: 1px solid #c6c6c6!important;
border: 1px solid #c6c6c6;
}
.btn[type='submit'] {
font-size: 1.5em;
@ -190,8 +188,6 @@ div.config-form .row.field {
}
/* Styles for form admin view (/forms/:formID/admin) */
.admin-form > .page-header {
padding-bottom: 0px;
@ -321,7 +317,9 @@ section > section.public-form {
margin-bottom: 45px;
}
.form-item.create-new input[type='text']{
/*width: inherit;*/
width: inherit;
color:black;
border:none;
}
.form-item.create-new {
@ -329,7 +327,7 @@ section > section.public-form {
color: white;
}
/*MODAL CSS */
/*CREATE-NEW FORM MODAL*/
.form-item.create-new.new-form {
background-color: rgb(300,131,131);
z-index: 11;
@ -337,9 +335,34 @@ section > section.public-form {
.form-item.create-new.new-form:hover {
background-color: rgb(300,100,100);
}
.form-item.new-form input[type='text'] {
margin-top:0.2em;
width: inherit;
color:black;
border:none;
padding: 0.3em 0.6em 0.3em 0.6em;
}
.form-item.new-form .custom-select {
margin-top: 0.2em
}
.form-item.new-form .custom-select select {
background-color: white;
}
.form-item.new-form a.btn {
font-size: 0.95em;
.form-item.new-form .details-row {
margin-top: 1em;
}
.form-item.new-form .details-row.submit {
margin-top: 1.7em;
}
.form-item.new-form .details-row.submit .btn {
font-size: 0.95em;
}
.form-item.new-form .title-row {
margin-top: 1em;
top:0;
}
/*Modal overlay (for lightbox effect)*/

View file

@ -214,7 +214,7 @@
it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', function() {
var controller = createAdminFormController();
//Set expected $state transition
//Set $state transition
$state.expectTransitionTo('listForms');
// Set DELETE response

View file

@ -192,38 +192,37 @@
var dupSampleForm = sampleFormList[2],
dupSampleForm_index = 3,
newSampleFormList = sampleFormList;
newSampleFormList = _.clone(sampleFormList);
dupSampleForm._id = 'a02df75b44c1d26b6a5e05b8';
newSampleFormList.splice(2, 0, dupSampleForm);
newSampleFormList.splice(3, 0, dupSampleForm);
var controller = createListFormsController();
// Set GET response
$httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList);
$httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList);
// Run controller functionality
scope.findAll();
$httpBackend.flush();
// Set GET response
$httpBackend.expect('POST', '/forms').respond(200, dupSampleForm);
// Run controller functionality
scope.duplicate(2);
$httpBackend.flush();
// Test scope value
expect( scope.myforms.length ).toEqual(sampleFormList.length+1);
// expect( scope.myforms ).toEqualData(newSampleFormList);
expect( scope.myforms.length ).toEqual(newSampleFormList.length);
for(var i=0; i<scope.myforms.length; i++){
expect( scope.myforms[i] ).toEqualData(newSampleFormList[i]);
}
expect( scope.myforms[dupSampleForm_index] ).toEqualData(dupSampleForm);
}));
it('$scope.removeForm() should remove a Form', inject(function(Forms) {
var delIndex = 0,
delSampleForm = sampleFormList[delIndex],
delSampleFormList = sampleFormList;
delSampleFormList = _.clone(sampleFormList);
delSampleFormList.splice(delIndex, 1);
var controller = createListFormsController();
@ -243,12 +242,43 @@
$httpBackend.flush();
// Test scope value
expect( scope.myforms.length ).toEqual(sampleFormList.length-1);
for(var i=0; i<scope.myforms.length){
expect( scope.myforms[i] ).toEqualData(sampleFormList.slice(1,2)[i]);
expect( scope.myforms.length ).toEqual(delSampleFormList.length);
for(var i=0; i<scope.myforms.length; i++){
expect( scope.myforms[i] ).toEqualData(delSampleFormList[i]);
}
expect( scope.myforms[0] ).not.toEqualData(delSampleForm);
}));
it('$scope.createNew() should create a new Form', inject(function(Forms) {
var newForm = _.clone(sampleForm);
newForm.name = 'Test Form5';
var controller = createListFormsController();
scope.forms.createForm = {
language: {
$modelValue: 'english'
},
title: {
$modelValue: 'Test Form5'
},
$dirty: true,
$valid: true,
}
// scope.forms.createForm.language.$modelValue = 'english';
// scope.forms.createForm.name.$modelValue = 'Test Form5';
// scope.forms.createForm.$dirty = true;
// scope.forms.createForm.$invalid = false;
//Set $state transition
$state.expectTransitionTo('viewForm');
// Set GET response
$httpBackend.expect('POST', '/forms').respond(200, newForm);
scope.createNew();
$httpBackend.flush();
}));
});

View file

@ -196,7 +196,9 @@
<input type="text"
ng-model="myform.title"
value="{{myform.title}}"
style="width: 100%;">
style="width: 100%;"
ng-minlength="4"
ng-pattern="/^[a-zA-Z0-9 \-.]*$/">
</div>
</div>

View file

@ -21,33 +21,32 @@
</div>
</div>
<form name="createForm" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item create-new new-form" ng-if="showCreateModal">
<div ng-init="setForm(createForm);" style="display:none;"></div>
<div class="title-row row">
<div class="col-xs-5 field-title">Name </div>
<div class="col-xs-12 field-input">
<input type="text" name="name" ng-model="name" required style="color:black; border:none;" ng-pattern="/^[a-zA-Z0-9 ]*$/"/>
</div>
</div>
<div class="details-row row">
<div class="col-xs-5 field-title text-left">
Language
<form name="forms.createForm" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item create-new new-form" ng-if="showCreateModal">
<div class="title-row row">
<div class="col-xs-5 field-title text-left"> Name </div>
<div class="col-xs-12 field-input">
<input type="text" name="title" required ng-pattern="/^[a-zA-Z0-9 \-.]*$/" ng-minlength="4"/>
</div>
<div class="col-xs-5 field-input">
</div>
<div class="details-row row">
<div class="col-xs-5 field-title text-left"> Language </div>
<div class="col-xs-12 field-input">
<div class="button custom-select">
<select style="color:black;" name="language" required ng-model="formLanguage" ng-init="formLanguage = user.language">
<option ng-repeat="language in languages" value="{{language}}">
{{language}}
</option>
</select>
</div>
</div>
<div class="details-row row">
<div class="col-xs-12 field-title text-center">
<button class="btn btn-primary" ng-disabled="myForm.$invalid" ng-click="createNew()">
Create Form
</button>
</div>
</div>
</div>
</div>
<div class="details-row submit row">
<div class="col-xs-12 field-title text-center">
<button class="btn btn-primary" ng-disabled="forms.createForm.$invalid" ng-click="createNew()">
Create Form
</button>
</div>
</div>
</form>
<div data-ng-repeat="form in myforms" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item container">

View file

@ -36,13 +36,11 @@
// var firstname = element(by.model('credentials.firstname')),
// lastname = element(by.model('credentials.lastname')),
// email = element(by.model('credentials.email')),
// password = element(by.model('credentials.password')),
// username = element(by.model('credentials.username'));
// password = element(by.model('credentials.password'));
// email.sendKeys('admin@app.com');
// username.sendKeys('admin');
// firstname.sendKeys('admin_first');
// firstname.sendKeys('admin_last');
// lastname.sendKeys('admin_last');
// password.sendKeys('1234');
// //Click signup button