From 52a305cf9ba242ec172e9620b637647ae47ee2de Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Tue, 18 Aug 2015 14:44:36 -0700 Subject: [PATCH] added testing --- app/controllers/forms.server.controller.js | 10 - .../users.authentication.server.controller.js | 2 +- app/models/form.server.model.js | 47 +- app/models/form_field.server.model.js | 106 +- app/models/form_submission.server.model.js | 7 - app/tests/form.server.model.test.js | 312 +++--- app/tests/form.server.routes.test.js | 966 +++++++++--------- app/tests/user.server.model.test.js | 156 +-- app/tests/user.server.routes.test.js | 174 ++-- bower.json | 14 +- config/env/test.js | 8 +- config/express.js | 2 +- .../base.css | 182 ++++ .../index.html | 60 ++ .../prettify.css | 1 + .../prettify.js | 1 + .../sort-arrow-sprite.png | Bin 0 -> 209 bytes .../sorter.js | 156 +++ .../PhantomJS 1.9.8 (Mac OS X 0.0.0)/base.css | 182 ++++ .../index.html | 60 ++ .../prettify.css | 1 + .../prettify.js | 1 + .../sort-arrow-sprite.png | Bin 0 -> 209 bytes .../sorter.js | 156 +++ gruntfile.js | 14 +- karma.conf.js | 11 +- package.json | 5 +- protractor.conf.js | 6 + public/dist/application.js | 717 +++---------- public/dist/application.min.js | 4 +- .../controllers/header.client.controller.js | 6 +- .../tests/header.client.controller.test.js | 38 +- .../core/tests/home.client.controller.test.js | 38 +- .../forms/config/forms.client.routes.js | 2 +- .../admin-form.client.controller.js | 115 +++ .../view-form.client.controller.js | 247 ----- public/modules/forms/css/form.css | 12 + .../configure-form.client.directive.js | 2 +- .../directives/edit-form.client.directive.js | 49 +- .../form-locator.client.directive.js | 8 - .../submissions-form.client.directive.js | 153 +++ .../submit-form.client.directive.js | 4 +- .../directives/table.client.directive.js | 15 +- .../admin-from.client.controller.test.js | 184 ++++ .../submissions-form.client.directive.test.js | 91 ++ .../tests/view-from.client.controller.test.js | 170 --- ....view.html => admin-form.client.view.html} | 135 ++- ...ng.html => update-form-message-TypeA.html} | 0 .../cgBusy/update-form-message-TypeB.html | 3 + ...m.html => configure-form.client.view.html} | 0 .../form/edit-form.client.view.html | 426 ++++++++ .../views/directiveViews/form/edit-form.html | 296 ------ .../form/submissions-form.client.view.html | 80 ++ ...form.html => submit-form.client.view.html} | 2 +- ...view.html => submit-form.client.view.html} | 0 .../{auth.js => auth.client.service.js} | 3 +- .../{user.js => user.client.service.js} | 0 .../authentication.client.controller.test.js | 276 ++--- 58 files changed, 3236 insertions(+), 2480 deletions(-) create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/base.css create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/index.html create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.css create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.js create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/sort-arrow-sprite.png create mode 100644 coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/sorter.js create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/base.css create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/index.html create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.css create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.js create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/sort-arrow-sprite.png create mode 100644 coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/sorter.js create mode 100644 protractor.conf.js create mode 100644 public/modules/forms/controllers/admin-form.client.controller.js delete mode 100644 public/modules/forms/controllers/view-form.client.controller.js delete mode 100644 public/modules/forms/directives/form-locator.client.directive.js create mode 100644 public/modules/forms/directives/submissions-form.client.directive.js create mode 100644 public/modules/forms/tests/admin-from.client.controller.test.js create mode 100644 public/modules/forms/tests/directives/submissions-form.client.directive.test.js delete mode 100644 public/modules/forms/tests/view-from.client.controller.test.js rename public/modules/forms/views/{view-form.client.view.html => admin-form.client.view.html} (56%) rename public/modules/forms/views/directiveViews/cgBusy/{updateFormLoading.html => update-form-message-TypeA.html} (100%) create mode 100644 public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html rename public/modules/forms/views/directiveViews/form/{configure-form.html => configure-form.client.view.html} (100%) create mode 100644 public/modules/forms/views/directiveViews/form/edit-form.client.view.html delete mode 100644 public/modules/forms/views/directiveViews/form/edit-form.html create mode 100644 public/modules/forms/views/directiveViews/form/submissions-form.client.view.html rename public/modules/forms/views/directiveViews/form/{submit-form.html => submit-form.client.view.html} (98%) rename public/modules/forms/views/{view-public-form.client.view.html => submit-form.client.view.html} (100%) rename public/modules/users/services/{auth.js => auth.client.service.js} (98%) rename public/modules/users/services/{user.js => user.client.service.js} (100%) diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index bfc12f9f..16cfe929 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -197,7 +197,6 @@ exports.create = function(req, res) { }); }; - /** * Show the current form */ @@ -209,23 +208,15 @@ exports.read = function(req, res) { * Update a form */ exports.update = function(req, res) { - // console.log('in form.update()'); - - // console.log(req.body.form.form_fields); - var form = req.form; delete req.body.form.__v; delete req.body.form._id; delete req.body.form.admin; - // console.log(form.admin); - //Unless we have 'admin' priviledges, updating form admin is disabled if(req.user.roles.indexOf('admin') === -1) delete req.body.form.admin; form = _.extend(form, req.body.form); - // console.log(req.body.form); - // form.form_fields = req.body.form.form_fields; form.save(function(err, form) { if (err) { @@ -234,7 +225,6 @@ exports.update = function(req, res) { message: errorHandler.getErrorMessage(err) }); } else { - // console.log('updated form'); res.json(form); } }); diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index eb2b582c..cbe2d4d8 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -105,7 +105,7 @@ exports.signin = function(req, res, next) { */ exports.signout = function(req, res) { req.logout(); - res.status(200).send('user successfully logged out'); + res.status(200).send('Successfully logged out'); // res.redirect('/'); }; diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 52455b09..966baf06 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -20,6 +20,25 @@ var FieldSchema = require('./form_field.server.model.js'), FormSubmission = mongoose.model('FormSubmission', FormSubmissionSchema); +var ButtonSchema = new Schema({ + url: { + type: String, + match: [/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/], + }, + action: String, + text: String, + bgColor: { + type: String, + match: [/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/], + default: '#5bc0de' + }, + color: { + type: String, + match: [/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/], + default: '#ffffff' + } +}); + /** * Form Schema */ @@ -73,30 +92,16 @@ var FormSchema = new Schema({ type: Boolean, default: false, }, - introText:{ + introTitle:{ + type: String, + default: 'Welcome to Form' + }, + introParagraph:{ type: String, }, - buttons:[{ - url: { - type: String, - match: [/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/], - }, - action: String, - buttonText: String, - backgroundColor: { - type: String, - match: [/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/], - default: '#5bc0de' - }, - color: { - type: String, - match: [/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/], - default: '#ffffff' - } - - - }] + buttons:[ButtonSchema] }, + hideFooter: { type: Boolean, default: false, diff --git a/app/models/form_field.server.model.js b/app/models/form_field.server.model.js index 0f537be3..c580d729 100644 --- a/app/models/form_field.server.model.js +++ b/app/models/form_field.server.model.js @@ -6,51 +6,18 @@ var mongoose = require('mongoose'), Schema = mongoose.Schema; -// questionType Validation -function validateFormFieldType(value) { - if (!value) { return false; } - - var validTypes = [ - 'textfield', - 'date', - 'email', - 'legal', - 'url', - 'textarea', - 'statement', - 'welcome', - 'thankyou', - 'file', - 'dropdown', - 'scale', - 'rating', - 'radio', - 'checkbox', - 'hidden', - 'yes_no', - 'natural', - 'number' - ]; - - if (validTypes.indexOf(value) > -1) { - return true; - } - return false; -} - - /** * Question Schema */ var FormFieldSchema = new Schema({ - // created: { - // type: Date, - // default: Date.now - // }, - // lastModified: { - // type: Date, - // default: Date.now - // }, + created: { + type: Date, + default: Date.now + }, + lastModified: { + type: Date, + default: Date.now + }, title: { type: String, default: '', @@ -86,6 +53,63 @@ var FormFieldSchema = new Schema({ }); +FormFieldSchema.static('validTypes', function(){ + return [ + 'textfield', + 'date', + 'email', + 'legal', + 'url', + 'textarea', + 'statement', + 'welcome', + 'thankyou', + 'file', + 'dropdown', + 'scale', + 'rating', + 'radio', + 'checkbox', + 'hidden', + 'yes_no', + 'natural', + 'number' + ]; +}); + +// fieldType Validation +function validateFormFieldType(value) { + if (!value) { return false; } + + var validTypes = [ + 'textfield', + 'date', + 'email', + 'legal', + 'url', + 'textarea', + 'statement', + 'welcome', + 'thankyou', + 'file', + 'dropdown', + 'scale', + 'rating', + 'radio', + 'checkbox', + 'hidden', + 'yes_no', + 'natural', + 'number' + ]; + + if (validTypes.indexOf(value) > -1) { + return true; + } + return false; +} + + module.exports = FormFieldSchema; // mongoose.model('Field', FormFieldSchema); \ No newline at end of file diff --git a/app/models/form_submission.server.model.js b/app/models/form_submission.server.model.js index 37b668f0..d8f59c64 100644 --- a/app/models/form_submission.server.model.js +++ b/app/models/form_submission.server.model.js @@ -91,7 +91,6 @@ FormSubmissionSchema.pre('save', function (next) { if(this.pdf && this.pdf.path){ - // console.log(this.pdf); dest_filename = that.title.replace(/ /g,'')+'_submission_'+Date.now()+'.pdf'; var __path = this.pdf.path.split('/').slice(0,this.pdf.path.split('/').length-1).join('/'); dest_path = path.join(__path, dest_filename); @@ -99,12 +98,6 @@ FormSubmissionSchema.pre('save', function (next) { that.pdfFilePath = dest_path; pdfFiller.fillForm(that.pdf.path, dest_path, that.fdfData, function(err){ - // console.log('fdfData: \n'); - // console.log(that.fdfData); - - // console.log('_form.pdf.path: '+_form.pdf.path); - // console.log('dest_path: '+dest_path); - if(err) { console.log('\n err.message: '+err.message); next( new Error(err.message) ); diff --git a/app/tests/form.server.model.test.js b/app/tests/form.server.model.test.js index 10712674..f1d73e3a 100644 --- a/app/tests/form.server.model.test.js +++ b/app/tests/form.server.model.test.js @@ -1,189 +1,189 @@ -// 'use strict'; +'use strict'; -// /** -// * Module dependencies. -// */ -// var should = require('should'), -// mongoose = require('mongoose'), -// User = mongoose.model('User'), -// Form = mongoose.model('Form'), -// _ = require('lodash'), -// FormSubmission = mongoose.model('FormSubmission'); +/** + * Module dependencies. + */ +var should = require('should'), + mongoose = require('mongoose'), + User = mongoose.model('User'), + Form = mongoose.model('Form'), + _ = require('lodash'), + FormSubmission = mongoose.model('FormSubmission'); -// /** -// * Globals -// */ -// var user, myForm, mySubmission; +/** + * Globals + */ +var user, myForm, mySubmission; -// /** -// * Unit tests -// */ -// describe('Form Model Unit Tests:', function() { -// beforeEach(function(done) { -// user = new User({ -// firstName: 'Full', -// lastName: 'Name', -// displayName: 'Full Name', -// email: 'test@test.com', -// username: 'username', -// password: 'password' -// }); +/** + * Unit tests + */ +describe('Form Model Unit Tests:', function() { + beforeEach(function(done) { + user = new User({ + firstName: 'Full', + lastName: 'Name', + displayName: 'Full Name', + email: 'test@test.com', + username: 'username', + password: 'password' + }); -// user.save(function() { -// myForm = new Form({ -// title: 'Form Title', -// admin: user, -// language: 'english', -// form_fields: [ -// {'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}, -// {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}, -// {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''} -// ] -// }); + user.save(function() { + myForm = new Form({ + title: 'Form Title', + admin: user, + language: 'english', + form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''} + ] + }); -// done(); -// }); -// }); + done(); + }); + }); -// describe('Method Save', function() { -// it('should be able to save without problems', function(done) { -// return myForm.save(function(err) { -// should.not.exist(err); -// done(); -// }); -// }); + describe('Method Save', function() { + it('should be able to save without problems', function(done) { + return myForm.save(function(err) { + should.not.exist(err); + done(); + }); + }); -// it('should be able to show an error when try to save without title', function(done) { -// var _form = myForm; -// _form.title = ''; + it('should be able to show an error when try to save without title', function(done) { + var _form = myForm; + _form.title = ''; -// return _form.save(function(err) { -// should.exist(err); -// should.equal(err.errors.title.message, 'Form Title cannot be blank'); -// done(); -// }); -// }); -// }); + return _form.save(function(err) { + should.exist(err); + should.equal(err.errors.title.message, 'Form Title cannot be blank'); + done(); + }); + }); + }); -// describe('Method Find', function(){ -// beforeEach(function(done){ -// myForm.save(function(err) { -// done(); -// }); -// }); -// it('should be able to findOne my form without problems', function(done) { -// return Form.findOne({_id: myForm._id}, function(err,form) { -// should.not.exist(err); -// should.exist(form); -// should.deepEqual(form.toObject(), myForm.toObject()); -// done(); -// }); -// }); -// }); + describe('Method Find', function(){ + beforeEach(function(done){ + myForm.save(function(err) { + done(); + }); + }); + it('should be able to findOne my form without problems', function(done) { + return Form.findOne({_id: myForm._id}, function(err,form) { + should.not.exist(err); + should.exist(form); + should.deepEqual(form.toObject(), myForm.toObject()); + done(); + }); + }); + }); -// describe('Test FormField and Submission Logic', function() { -// var new_form_fields_add1, new_form_fields_del, submission_fields, old_fields, form; + describe('Test FormField and Submission Logic', function() { + var new_form_fields_add1, new_form_fields_del, submission_fields, old_fields, form; -// before(function(){ -// new_form_fields_add1 = _.clone(myForm.toObject().form_fields); -// new_form_fields_add1.push( -// {'fieldType':'textfield', 'title':'Last Name', 'fieldValue': ''} -// ); + before(function(){ + new_form_fields_add1 = _.clone(myForm.toObject().form_fields); + new_form_fields_add1.push( + {'fieldType':'textfield', 'title':'Last Name', 'fieldValue': ''} + ); -// new_form_fields_del = _.clone(myForm.toObject().form_fields); -// new_form_fields_del.splice(0, 1); + new_form_fields_del = _.clone(myForm.toObject().form_fields); + new_form_fields_del.splice(0, 1); -// submission_fields = _.clone(myForm.toObject().form_fields); -// submission_fields[0].fieldValue = 'David'; -// submission_fields[1].fieldValue = true; -// submission_fields[2].fieldValue = true; + submission_fields = _.clone(myForm.toObject().form_fields); + submission_fields[0].fieldValue = 'David'; + submission_fields[1].fieldValue = true; + submission_fields[2].fieldValue = true; -// mySubmission = new FormSubmission({ -// form_fields: submission_fields, -// admin: user, -// form: myForm, -// timeElapsed: 17.55 -// }); + mySubmission = new FormSubmission({ + form_fields: submission_fields, + admin: user, + form: myForm, + timeElapsed: 17.55 + }); -// }); + }); -// beforeEach(function(done){ -// myForm.save(function(){ -// mySubmission.save(function(){ -// done(); -// }); -// }); -// }); + beforeEach(function(done){ + myForm.save(function(){ + mySubmission.save(function(){ + done(); + }); + }); + }); -// afterEach(function(done){ -// mySubmission.remove(function(){ -// done(); -// }); -// }); + afterEach(function(done){ + mySubmission.remove(function(){ + done(); + }); + }); -// // it('should preserve deleted form_fields that have submissions without any problems', function(done) { + // it('should preserve deleted form_fields that have submissions without any problems', function(done) { -// // old_fields = myForm.toObject().form_fields; -// // // console.log(old_fields); + // old_fields = myForm.toObject().form_fields; + // // console.log(old_fields); -// // // var expected_fields = old_fields.slice(1,3).concat(old_fields.slice(0,1)); + // // var expected_fields = old_fields.slice(1,3).concat(old_fields.slice(0,1)); -// // myForm.form_fields = new_form_fields_del; + // myForm.form_fields = new_form_fields_del; -// // myForm.save(function(err, _form) { + // myForm.save(function(err, _form) { -// // should.not.exist(err); -// // should.exist(_form); + // should.not.exist(err); + // should.exist(_form); -// // // var actual_fields = _.map(_form.toObject().form_fields, function(o){ _.omit(o, '_id')}); -// // // old_fields = _.map(old_fields, function(o){ _.omit(o, '_id')}); + // // var actual_fields = _.map(_form.toObject().form_fields, function(o){ _.omit(o, '_id')}); + // // old_fields = _.map(old_fields, function(o){ _.omit(o, '_id')}); -// // // console.log(old_fields); -// // should.deepEqual(JSON.stringify(_form.toObject().form_fields), JSON.stringify(old_fields), 'old form_fields not equal to newly saved form_fields'); -// // done(); -// // }); -// // }); + // // console.log(old_fields); + // should.deepEqual(JSON.stringify(_form.toObject().form_fields), JSON.stringify(old_fields), 'old form_fields not equal to newly saved form_fields'); + // done(); + // }); + // }); -// // it('should delete \'preserved\' form_fields whose submissions have been removed without any problems', function(done) { + // it('should delete \'preserved\' form_fields whose submissions have been removed without any problems', function(done) { -// // myForm.form_fields = new_form_fields_del; -// // myForm.save(function(err, form -// // should.not.exist(err); -// // (form.form_fields).should.be.eql(old_fields, 'old form_fields not equal to newly saved form_fields'); + // myForm.form_fields = new_form_fields_del; + // myForm.save(function(err, form + // should.not.exist(err); + // (form.form_fields).should.be.eql(old_fields, 'old form_fields not equal to newly saved form_fields'); -// // //Remove submission -// // mySubmission.remove(function(err){ -// // myForm.submissions.should.have.length(0); -// // myForm.form_fields.should.not.containDeep(old_fields[0]); -// // }); -// // }); -// // }); -// }); + // //Remove submission + // mySubmission.remove(function(err){ + // myForm.submissions.should.have.length(0); + // myForm.form_fields.should.not.containDeep(old_fields[0]); + // }); + // }); + // }); + }); -// // describe('Method generateFDFTemplate', function() { -// // var FormFDF; -// // before(function(done){ -// // return myForm.save(function(err, form){ + // describe('Method generateFDFTemplate', function() { + // var FormFDF; + // before(function(done){ + // return myForm.save(function(err, form){ -// // FormFDF = { -// // 'First Name': '', -// // 'nascar': '', -// // 'hockey': '' -// // }; -// // done(); -// // }); -// // }); + // FormFDF = { + // 'First Name': '', + // 'nascar': '', + // 'hockey': '' + // }; + // done(); + // }); + // }); -// // it('should be able to generate a FDF template without any problems', function() { -// // var fdfTemplate = myForm.generateFDFTemplate(); -// // (fdfTemplate).should.be.eql(FormFDF); -// // }); -// // }); + // it('should be able to generate a FDF template without any problems', function() { + // var fdfTemplate = myForm.generateFDFTemplate(); + // (fdfTemplate).should.be.eql(FormFDF); + // }); + // }); -// afterEach(function(done) { -// Form.remove().exec(function() { -// User.remove().exec(done); -// }); -// }); -// }); + afterEach(function(done) { + Form.remove().exec(function() { + User.remove().exec(done); + }); + }); +}); diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index 0cad5fe3..c4c665cc 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -1,496 +1,502 @@ -// 'use strict'; - -// var should = require('should'), -// _ = require('lodash'), -// app = require('../../server'), -// request = require('supertest'), -// Session = require('supertest-session')({ -// app: app -// }), -// mongoose = require('mongoose'), -// User = mongoose.model('User'), -// Form = mongoose.model('Form'), -// FormSubmission = mongoose.model('FormSubmission'), -// agent = request.agent(app); - -// /** -// * Globals -// */ -// var credentials, user, _Form; - -// /** -// * Form routes tests -// */ -// describe('Form CRUD tests', function() { - -// beforeEach(function(done) { -// // Create user credentials -// credentials = { -// username: 'test@test.com', -// password: 'password' -// }; - -// // Create a new user -// user = new User({ -// firstName: 'Full', -// lastName: 'Name', -// email: 'test@test.com', -// username: credentials.username, -// password: credentials.password, -// provider: 'local' -// }); - -// // Save a user to the test db and create new Form -// user.save(function(err) { -// if(err) done(err); -// _Form = { -// title: 'Form Title', -// language: 'english', -// admin: user._id, -// form_fields: [ -// {'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}, -// {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}, -// {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''} -// ] -// }; - -// done(); -// }); -// }); - -// it('should be able to save a Form if logged in', function(done) { -// agent.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { - -// // Handle signin error -// if (signinErr) done(signinErr); - -// var user = signinRes.body; -// var userId = user._id; - -// // Save a new Form -// agent.post('/forms') -// .send({form: _Form}) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormSaveErr, FormSaveRes) { -// // Handle Form save error -// if (FormSaveErr) done(FormSaveErr); - -// // Get a list of Forms -// agent.get('/forms') -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormsGetErr, FormsGetRes) { -// // Handle Form save error -// if (FormsGetErr) done(FormsGetErr); - -// // Get Forms list -// var Forms = FormsGetRes.body; - -// // Set assertions -// (Forms[0].admin).should.equal(userId); -// (Forms[0].title).should.match('Form Title'); - -// // Call the assertion callback -// done(); -// }); - -// }); - - -// }); -// }); - -// it('should not be able to create a Form if not logged in', function(done) { -// agent.post('/forms') -// .send({form: _Form}) -// .expect(401) -// .end(function(FormSaveErr, FormSaveRes) { -// (FormSaveRes.body.message).should.equal('User is not logged in'); -// // Call the assertion callback -// done(FormSaveErr); -// }); -// }); - -// it('should not be able to get list of users\' Forms if not logged in', function(done) { -// agent.get('/forms') -// .expect(401) -// .end(function(FormSaveErr, FormSaveRes) { -// (FormSaveRes.body.message).should.equal('User is not logged in'); -// // Call the assertion callback -// done(FormSaveErr); -// }); -// }); - -// it('should not be able to save a Form if no title is provided', function(done) { -// // Set Form with a invalid title field -// _Form.title = ''; - -// agent.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { -// // Handle signin error -// if (signinErr) done(signinErr); - -// // Save a new Form -// agent.post('/forms') -// .send({form: _Form}) -// .expect(400) -// .end(function(FormSaveErr, FormSaveRes) { -// // Set message assertion -// (FormSaveRes.body.message).should.equal('Form Title cannot be blank'); - -// // Handle Form save error -// done(); -// }); -// }); -// }); - -// it('should be able to update a Form if signed in', function(done) { -// agent.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { -// // Handle signin error -// if (signinErr) done(signinErr); - -// // Save a new Form -// agent.post('/forms') -// .send({form: _Form}) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormSaveErr, FormSaveRes) { -// // Handle Form save error -// if (FormSaveErr) done(FormSaveErr); - -// // Update Form title -// _Form.title = 'WHY YOU GOTTA BE SO MEAN?'; - -// // Update an existing Form -// agent.put('/forms/' + FormSaveRes.body._id) -// .send({form: _Form}) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormUpdateErr, FormUpdateRes) { -// // Handle Form update error -// if (FormUpdateErr) done(FormUpdateErr); - -// // Set assertions -// (FormUpdateRes.body._id).should.equal(FormSaveRes.body._id); -// (FormUpdateRes.body.title).should.match('WHY YOU GOTTA BE SO MEAN?'); - -// // Call the assertion callback -// done(); -// }); -// }); -// }); -// }); - -// it('should be able to read/get a Form if not signed in', function(done) { -// // Create new Form model instance -// var FormObj = new Form(_Form); - -// // Save the Form -// FormObj.save(function(err, form) { -// if(err) done(err); - -// request(app).get('/forms/' + form._id) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(err, res) { -// if(err) done(err) - -// // Set assertion -// (res.body).should.be.an.Object.with.property('title', _Form.title); - -// // Call the assertion callback -// done(); -// }); -// }); -// }); - -// it('should be able to delete a Form if signed in', function(done) { - -// agent.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { -// // Handle signin error -// if (signinErr) done(signinErr); - -// done(); -// // Save a new Form -// // agent.post('/forms') -// // .send({form: _Form}) -// // .expect('Content-Type', /json/) -// // .expect(200) -// // .end(function(FormSaveErr, FormSaveRes) { -// // // Handle Form save error -// // if (FormSaveErr) done(FormSaveErr); - -// // // Delete an existing Form -// // agent.delete('/forms/' + FormSaveRes.body._id) -// // .send(_Form) -// // .expect('Content-Type', /json/) -// // .expect(200) -// // .end(function(FormDeleteErr, FormDeleteRes) { -// // // Handle Form error error -// // if (FormDeleteErr) done(FormDeleteErr); - -// // // Set assertions -// // (FormDeleteRes.body._id).should.equal(FormSaveRes.body._id); - -// // // Call the assertion callback -// // done(); -// // }); -// // }); - -// }); -// }); - -// it('should not be able to delete an Form if not signed in', function(done) { -// // Set Form user -// _Form.admin = user; - -// // Create new Form model instance -// var FormObj = new Form(_Form); - -// // Save the Form -// FormObj.save(function() { -// // Try deleting Form -// request(app).delete('/forms/' + FormObj._id) -// .expect(401) -// .end(function(FormDeleteErr, FormDeleteRes) { -// // Set message assertion -// (FormDeleteRes.body.message).should.match('User is not logged in'); - -// // Handle Form error error -// done(FormDeleteErr); -// }); - -// }); -// }); - - -// it('should be able to upload a PDF an Form if logged in', function(done) { -// agent.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { - -// // Handle signin error -// if (signinErr) done(signinErr); - -// var user = signinRes.body; -// var userId = user._id; - -// // Save a new Form -// agent.post('/forms') -// .send({form: _Form}) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormSaveErr, FormSaveRes) { -// // Handle Form save error -// if (FormSaveErr) done(FormSaveErr); - -// // Get a list of Forms -// agent.get('/forms') -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(FormsGetErr, FormsGetRes) { -// // Handle Form save error -// if (FormsGetErr) done(FormsGetErr); - -// // Get Forms list -// var Forms = FormsGetRes.body; - -// // Set assertions -// (Forms[0].admin).should.equal(userId); -// (Forms[0].title).should.match('Form Title'); - -// // Call the assertion callback -// done(); -// }); - -// }); - - -// }); -// }); - -// describe('Form Submission tests', function() { -// var FormObj, _Submission, submissionSession; - -// beforeEach(function (done) { -// _Form.admin = user; -// FormObj = new Form(_Form); - -// FormObj.save(function(err, form) { -// if (err) done(err); - -// _Submission = { -// form_fields: [ -// {'fieldType':'textfield', 'title':'First Name', 'fieldValue': 'David'}, -// {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': true}, -// {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': false} -// ], -// form: form._id, -// admin: user._id, -// percentageComplete: 100, -// timeElapsed: 11.55 -// }; - -// FormObj = form; - -// //Setup test session -// submissionSession = new Session(); - -// done(); -// }); -// }); - -// it('should be able to create a Form Submission without signing in', function(done) { - -// //Create Submission -// submissionSession.post('/forms/' + FormObj._id) -// .send(_Submission) -// .expect(200) -// .end(function(err, res) { - -// should.not.exist(err); - -// done(); -// }); -// }); - -// it('should be able to get Form Submissions if signed in', function(done) { -// submissionSession.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { - -// should.not.exist(signinErr); - -// //Create Submission -// submissionSession.post('/forms/' + FormObj._id) -// .send(_Submission) -// .expect(200) -// .end(function(err, res) { - -// should.not.exist(err); - -// submissionSession.get('/forms/' + FormObj._id + '/submissions') -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(err, res) { - -// // Set assertion -// should.not.exist(err); - -// // Call the assertion callback -// done(); -// }); -// }); -// }); -// }); - -// it('should not be able to get Form Submissions if not signed in', function(done) { -// // Attempt to fetch form submissions -// submissionSession.get('/forms/' + FormObj._id + '/submissions') -// .expect(401) -// .end(function(err, res) { +'use strict'; + +var should = require('should'), + _ = require('lodash'), + app = require('../../server'), + request = require('supertest'), + Session = require('supertest-session')({ + app: app + }), + mongoose = require('mongoose'), + User = mongoose.model('User'), + Form = mongoose.model('Form'), + FormSubmission = mongoose.model('FormSubmission'), + agent = request.agent(app); + +/** + * Globals + */ +var credentials, user, _Form; + +/** + * Form routes tests + */ +describe('Form CRUD tests', function() { + + beforeEach(function(done) { + + //Initialize Session + userSession = new Session(); + + // Create user credentials + credentials = { + username: 'test@test.com', + password: 'password' + }; + + // Create a new user + user = new User({ + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: credentials.username, + password: credentials.password, + provider: 'local' + }); + + // Save a user to the test db and create new Form + user.save(function(err) { + if(err) done(err); + _Form = { + title: 'Form Title', + language: 'english', + admin: user._id, + form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''} + ] + }; + + done(); + }); + }); + + it('should be able to save a Form if logged in', function(done) { + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + + // Handle signin error + if (signinErr) done(signinErr); + + var user = signinRes.body; + var userId = user._id; + + // Save a new Form + userSession.post('/forms') + .send({form: _Form}) + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormSaveErr, FormSaveRes) { + // Handle Form save error + if (FormSaveErr) done(FormSaveErr); + + // Get a list of Forms + userSession.get('/forms') + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormsGetErr, FormsGetRes) { + // Handle Form save error + if (FormsGetErr) done(FormsGetErr); + + // Get Forms list + var Forms = FormsGetRes.body; + + // Set assertions + (Forms[0].admin).should.equal(userId); + (Forms[0].title).should.match('Form Title'); + + // Call the assertion callback + done(); + }); + + }); + + + }); + }); + + it('should not be able to create a Form if not logged in', function(done) { + userSession.post('/forms') + .send({form: _Form}) + .expect(401) + .end(function(FormSaveErr, FormSaveRes) { + (FormSaveRes.body.message).should.equal('User is not logged in'); + // Call the assertion callback + done(FormSaveErr); + }); + }); + + it('should not be able to get list of users\' Forms if not logged in', function(done) { + userSession.get('/forms') + .expect(401) + .end(function(FormSaveErr, FormSaveRes) { + (FormSaveRes.body.message).should.equal('User is not logged in'); + // Call the assertion callback + done(FormSaveErr); + }); + }); + + it('should not be able to save a Form if no title is provided', function(done) { + // Set Form with a invalid title field + _Form.title = ''; + + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + // Handle signin error + if (signinErr) done(signinErr); + + // Save a new Form + userSession.post('/forms') + .send({form: _Form}) + .expect(400) + .end(function(FormSaveErr, FormSaveRes) { + // Set message assertion + (FormSaveRes.body.message).should.equal('Form Title cannot be blank'); + + // Handle Form save error + done(); + }); + }); + }); + + it('should be able to update a Form if signed in', function(done) { + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + // Handle signin error + if (signinErr) done(signinErr); + + // Save a new Form + userSession.post('/forms') + .send({form: _Form}) + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormSaveErr, FormSaveRes) { + // Handle Form save error + if (FormSaveErr) done(FormSaveErr); + + // Update Form title + _Form.title = 'WHY YOU GOTTA BE SO MEAN?'; + + // Update an existing Form + userSession.put('/forms/' + FormSaveRes.body._id) + .send({form: _Form}) + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormUpdateErr, FormUpdateRes) { + // Handle Form update error + if (FormUpdateErr) done(FormUpdateErr); + + // Set assertions + (FormUpdateRes.body._id).should.equal(FormSaveRes.body._id); + (FormUpdateRes.body.title).should.match('WHY YOU GOTTA BE SO MEAN?'); + + // Call the assertion callback + done(); + }); + }); + }); + }); + + it('should be able to read/get a Form if not signed in', function(done) { + // Create new Form model instance + var FormObj = new Form(_Form); + + // Save the Form + FormObj.save(function(err, form) { + if(err) done(err); + + request(app).get('/forms/' + form._id) + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if(err) done(err) + + // Set assertion + (res.body).should.be.an.Object.with.property('title', _Form.title); + + // Call the assertion callback + done(); + }); + }); + }); + + it('should be able to delete a Form if signed in', function(done) { + + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + // Handle signin error + if (signinErr) done(signinErr); + + done(); + // Save a new Form + // userSession.post('/forms') + // .send({form: _Form}) + // .expect('Content-Type', /json/) + // .expect(200) + // .end(function(FormSaveErr, FormSaveRes) { + // // Handle Form save error + // if (FormSaveErr) done(FormSaveErr); + + // // Delete an existing Form + // userSession.delete('/forms/' + FormSaveRes.body._id) + // .send(_Form) + // .expect('Content-Type', /json/) + // .expect(200) + // .end(function(FormDeleteErr, FormDeleteRes) { + // // Handle Form error error + // if (FormDeleteErr) done(FormDeleteErr); + + // // Set assertions + // (FormDeleteRes.body._id).should.equal(FormSaveRes.body._id); + + // // Call the assertion callback + // done(); + // }); + // }); + + }); + }); + + it('should not be able to delete an Form if not signed in', function(done) { + // Set Form user + _Form.admin = user; + + // Create new Form model instance + var FormObj = new Form(_Form); + + // Save the Form + FormObj.save(function() { + // Try deleting Form + request(app).delete('/forms/' + FormObj._id) + .expect(401) + .end(function(FormDeleteErr, FormDeleteRes) { + // Set message assertion + (FormDeleteRes.body.message).should.match('User is not logged in'); + + // Handle Form error error + done(FormDeleteErr); + }); + + }); + }); + + + it('should be able to upload a PDF an Form if logged in', function(done) { + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + + // Handle signin error + if (signinErr) done(signinErr); + + var user = signinRes.body; + var userId = user._id; + + // Save a new Form + userSession.post('/forms') + .send({form: _Form}) + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormSaveErr, FormSaveRes) { + // Handle Form save error + if (FormSaveErr) done(FormSaveErr); + + // Get a list of Forms + userSession.get('/forms') + .expect('Content-Type', /json/) + .expect(200) + .end(function(FormsGetErr, FormsGetRes) { + // Handle Form save error + if (FormsGetErr) done(FormsGetErr); + + // Get Forms list + var Forms = FormsGetRes.body; + + // Set assertions + (Forms[0].admin).should.equal(userId); + (Forms[0].title).should.match('Form Title'); + + // Call the assertion callback + done(); + }); + + }); + + + }); + }); + + describe('Form Submission tests', function() { + var FormObj, _Submission, submissionSession; + + beforeEach(function (done) { + _Form.admin = user; + FormObj = new Form(_Form); + + FormObj.save(function(err, form) { + if (err) done(err); + + _Submission = { + form_fields: [ + {'fieldType':'textfield', 'title':'First Name', 'fieldValue': 'David'}, + {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': true}, + {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': false} + ], + form: form._id, + admin: user._id, + percentageComplete: 100, + timeElapsed: 11.55 + }; + + FormObj = form; + + //Setup test session + submissionSession = new Session(); + + done(); + }); + }); + + it('should be able to create a Form Submission without signing in', function(done) { + + //Create Submission + submissionSession.post('/forms/' + FormObj._id) + .send(_Submission) + .expect(200) + .end(function(err, res) { + + should.not.exist(err); + + done(); + }); + }); + + it('should be able to get Form Submissions if signed in', function(done) { + submissionSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + + should.not.exist(signinErr); + + //Create Submission + submissionSession.post('/forms/' + FormObj._id) + .send(_Submission) + .expect(200) + .end(function(err, res) { + + should.not.exist(err); + + submissionSession.get('/forms/' + FormObj._id + '/submissions') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + + // Set assertion + should.not.exist(err); + + // Call the assertion callback + done(); + }); + }); + }); + }); + + it('should not be able to get Form Submissions if not signed in', function(done) { + // Attempt to fetch form submissions + submissionSession.get('/forms/' + FormObj._id + '/submissions') + .expect(401) + .end(function(err, res) { -// // Set assertions -// (res.body.message).should.equal('User is not logged in'); + // Set assertions + (res.body.message).should.equal('User is not logged in'); -// // Call the assertion callback -// done(); -// }); -// }); + // Call the assertion callback + done(); + }); + }); -// it('should not be able to delete Form Submission if not signed in', function(done) { -// var SubmissionObj = new FormSubmission(_Submission); + it('should not be able to delete Form Submission if not signed in', function(done) { + var SubmissionObj = new FormSubmission(_Submission); -// SubmissionObj.save(function (err, submission) { -// should.not.exist(err); - -// var submission_ids = _.pluck([submission], '_id'); - -// // Attempt to delete form submissions -// submissionSession.delete('/forms/' + FormObj._id + '/submissions') -// .send({deleted_submissions: submission_ids}) -// .expect(401) -// .end(function(err, res) { + SubmissionObj.save(function (err, submission) { + should.not.exist(err); + + var submission_ids = _.pluck([submission], '_id'); + + // Attempt to delete form submissions + submissionSession.delete('/forms/' + FormObj._id + '/submissions') + .send({deleted_submissions: submission_ids}) + .expect(401) + .end(function(err, res) { -// // Set assertions -// should.not.exist(err); -// (res.body.message).should.equal('User is not logged in'); + // Set assertions + should.not.exist(err); + (res.body.message).should.equal('User is not logged in'); -// // Call the assertion callback -// done(); -// }); -// }); -// }); + // Call the assertion callback + done(); + }); + }); + }); -// it('should be able to delete Form Submission if signed in', function(done) { -// // Create new FormSubmission model instance -// var SubmissionObj = new FormSubmission(_Submission); + it('should be able to delete Form Submission if signed in', function(done) { + // Create new FormSubmission model instance + var SubmissionObj = new FormSubmission(_Submission); -// SubmissionObj.save(function (err, submission) { -// should.not.exist(err); + SubmissionObj.save(function (err, submission) { + should.not.exist(err); -// // Signin as user -// submissionSession.post('/auth/signin') -// .send(credentials) -// .expect('Content-Type', /json/) -// .expect(200) -// .end(function(signinErr, signinRes) { -// // Handle signin error -// if (signinErr) done(signinErr); + // Signin as user + submissionSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(signinErr, signinRes) { + // Handle signin error + if (signinErr) done(signinErr); -// var submission_ids = _.pluck([submission], '_id'); + var submission_ids = _.pluck([submission], '_id'); -// //Delete form submissions -// submissionSession.delete('/forms/' + FormObj._id + '/submissions') -// .send({deleted_submissions: submission_ids}) -// .expect(200) -// .end(function(err, res) { + //Delete form submissions + submissionSession.delete('/forms/' + FormObj._id + '/submissions') + .send({deleted_submissions: submission_ids}) + .expect(200) + .end(function(err, res) { -// // Set assertions -// should.not.exist(err); -// (res.text).should.equal('Form submissions successfully deleted'); + // Set assertions + should.not.exist(err); + (res.text).should.equal('Form submissions successfully deleted'); -// // Call the assertion callback -// done(); -// }); -// }); -// }); -// }); + // Call the assertion callback + done(); + }); + }); + }); + }); -// afterEach(function(done) {//logout current user if there is one -// FormSubmission.remove().exec(function() { -// Form.remove().exec(function (err) { -// submissionSession.destroy(); -// done(); -// }); -// }); -// }); -// }); + afterEach(function(done) {//logout current user if there is one + FormSubmission.remove().exec(function() { + Form.remove().exec(function (err) { + submissionSession.destroy(); + done(); + }); + }); + }); + }); -// afterEach(function(done) { -// User.remove().exec(function() { -// Form.remove().exec(done); -// }); -// }); -// }); + afterEach(function(done) { + User.remove().exec(function() { + Form.remove().exec(function() { + userSession.destroy(); + }); + }); + }); +}); diff --git a/app/tests/user.server.model.test.js b/app/tests/user.server.model.test.js index 56d709a4..e58744d8 100755 --- a/app/tests/user.server.model.test.js +++ b/app/tests/user.server.model.test.js @@ -1,90 +1,90 @@ -// 'use strict'; +'use strict'; -// /** -// * Module dependencies. -// */ -// var should = require('should'), -// mongoose = require('mongoose'), -// User = mongoose.model('User'); +/** + * Module dependencies. + */ +var should = require('should'), + mongoose = require('mongoose'), + User = mongoose.model('User'); -// /** -// * Globals -// */ -// var user, user2; +/** + * Globals + */ +var user, user2; -// /** -// * Unit tests -// */ -// describe('User Model Unit Tests:', function() { -// beforeEach(function(done) { -// user = new User({ -// firstName: 'Full', -// lastName: 'Name', -// email: 'test@test.com', -// username: 'test@test.com', -// password: 'password', -// provider: 'local' -// }); -// user2 = new User({ -// firstName: 'Full', -// lastName: 'Name', -// email: 'test@test.com', -// username: 'test@test.com', -// password: 'password', -// provider: 'local' -// }); +/** + * Unit tests + */ +describe('User Model Unit Tests:', function() { + beforeEach(function(done) { + user = new User({ + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local' + }); + user2 = new User({ + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + password: 'password', + provider: 'local' + }); -// done(); -// }); + done(); + }); -// describe('Method Save', function() { -// it('should begin with no users', function(done) { -// User.find({}, function(err, users) { -// users.should.have.length(0); -// done(); -// }); -// }); + describe('Method Save', function() { + it('should begin with no users', function(done) { + User.find({}, function(err, users) { + users.should.have.length(0); + done(); + }); + }); -// it('should be able to save without problems', function(done) { -// user.save(done); -// }); + it('should be able to save without problems', function(done) { + user.save(done); + }); -// it('should fail to save an existing user again', function(done) { -// user.save(function() { -// user2.save(function(err) { -// should.exist(err); -// done(); -// }); -// }); -// }); + it('should fail to save an existing user again', function(done) { + user.save(function() { + user2.save(function(err) { + should.exist(err); + done(); + }); + }); + }); -// it('should be able to show an error when try to save without first name', function(done) { -// user.firstName = ''; -// return user.save(function(err) { -// should.exist(err); -// done(); -// }); -// }); -// }); + it('should be able to show an error when try to save without first name', function(done) { + user.firstName = ''; + return user.save(function(err) { + should.exist(err); + done(); + }); + }); + }); -// describe('Method findUniqueUsername', function() { -// beforeEach(function(done) { -// User.find({}, function(err, users) { -// users.should.have.length(0); -// user.save(done); -// }); -// }); + describe('Method findUniqueUsername', function() { + beforeEach(function(done) { + User.find({}, function(err, users) { + users.should.have.length(0); + user.save(done); + }); + }); -// it('should be able to find unique version of existing username without problems', function(done) { -// User.findUniqueUsername(user.username, null, function (availableUsername) { -// availableUsername.should.not.equal(user.username); -// done(); -// }); -// }); + it('should be able to find unique version of existing username without problems', function(done) { + User.findUniqueUsername(user.username, null, function (availableUsername) { + availableUsername.should.not.equal(user.username); + done(); + }); + }); -// }); + }); -// afterEach(function(done) { -// User.remove().exec(done); -// }); -// }); + afterEach(function(done) { + User.remove().exec(done); + }); +}); diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 2072f776..eb5ae267 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -17,6 +17,9 @@ var should = require('should'), var mailosaur = require('mailosaur')(config.mailosaur.key), mailbox = new mailosaur.Mailbox(config.mailosaur.mailbox_id); +var mandrill = require('node-mandrill')(config.mailer.options.auth.pass); + + /** * Globals */ @@ -26,7 +29,7 @@ var credentials, _User, _Session; * Form routes tests */ describe('User CRUD tests', function() { - this.timeout(10000); + this.timeout(15000); var userSession; beforeEach(function(done) { @@ -52,11 +55,9 @@ describe('User CRUD tests', function() { }); - - describe('create, activate and confirm a User Account', function () { var username = 'testActiveAccount.be1e58fb@mailosaur.in'; - var link, activateToken; + var link, _tmpUser, activateToken = ''; it('should be able to create a temporary (non-activated) User', function(done) { _User.email = _User.username = username; @@ -66,89 +67,142 @@ describe('User CRUD tests', function() { .end(function(FormSaveErr, FormSaveRes) { (FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.'); - // setTimeout(function() { + setTimeout(function() { tmpUser.findOne({username: _User.username}, function (err, user) { should.not.exist(err); should.exist(user); + _tmpUser = user; _User.username.should.equal(user.username); _User.firstName.should.equal(user.firstName); _User.lastName.should.equal(user.lastName); - mailbox.getEmails(function(err, _emails) { - if(err) done(err); - var emails = _emails; + mandrill('/messages/search', { + query: "subject:Confirm", + senders: [ + "test@forms.polydaic.com" + ], + limit: 1 + }, function(error, emails) { + if (error) console.log( JSON.stringify(error) ); - console.log('mailbox.getEmails:'); - for(var i=0; i (http://baldwynn.me)" @@ -11,10 +11,10 @@ "appPath": "public/modules", "dependencies": { "bootstrap": "~3", - "angular": "~1.3.17", - "angular-resource": "~1.2", + "angular": "^1.3.17", + "angular-resource": "~1.4.4", "angular-animate": "~1.3", - "angular-mocks": "~1.2", + "angular-mocks": "1.3.0", "angular-bootstrap": "~0.12.0", "angular-ui-utils": "~0.1.1", "angular-ui-router": "~0.2.11", @@ -28,9 +28,7 @@ "angular-ui-sortable": "~0.13.4", "angular-busy": "~4.1.3", "angular-permission": "~0.3.1", - "angular-input-stars": "*" - }, - "resolutions": { - "angular": "~1.3.17" + "angular-input-stars": "~1.5.5", + "file-saver.js": "~1.20150507.2" } } diff --git a/config/env/test.js b/config/env/test.js index 3b0605c4..fd557264 100755 --- a/config/env/test.js +++ b/config/env/test.js @@ -20,7 +20,7 @@ module.exports = { } }, app: { - title: 'MedForms' + title: 'MedForms Test' }, facebook: { clientID: process.env.FACEBOOK_ID || 'APP_ID', @@ -50,10 +50,10 @@ module.exports = { mailer: { from: process.env.MAILER_FROM || 'MAILER_FROM', options: { - service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER', + service: process.env.MAILER_SERVICE_PROVIDER || '', auth: { - user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID', - pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD' + user: process.env.MAILER_EMAIL_ID || '', + pass: process.env.MAILER_PASSWORD || '' } } } diff --git a/config/express.js b/config/express.js index 49b09023..88027cdb 100755 --- a/config/express.js +++ b/config/express.js @@ -51,7 +51,7 @@ var config_nev = function () { confirmMailOptions: { from: config.mailer.from, - subject: 'Successfully verified!', + subject: 'Account successfully verified!', html: '

Your account has been successfully verified.

', text: 'Your account has been successfully verified.' }, diff --git a/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/base.css b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/base.css new file mode 100644 index 00000000..a9d48374 --- /dev/null +++ b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/base.css @@ -0,0 +1,182 @@ +body, html { + margin:0; padding: 0; +} +body { + font-family: Helvetica Neue, Helvetica,Arial; + font-size: 10pt; +} +div.header, div.footer { + background: #eee; + padding: 1em; +} +div.header { + z-index: 100; + position: fixed; + top: 0; + border-bottom: 1px solid #666; + width: 100%; +} +div.footer { + border-top: 1px solid #666; +} +div.body { + margin-top: 10em; +} +div.meta { + font-size: 90%; + text-align: center; +} +h1, h2, h3 { + font-weight: normal; +} +h1 { + font-size: 12pt; +} +h2 { + font-size: 10pt; +} +pre { + font-family: Consolas, Menlo, Monaco, monospace; + margin: 0; + padding: 0; + line-height: 14px; + font-size: 14px; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} + +div.path { font-size: 110%; } +div.path a:link, div.path a:visited { color: #000; } +table.coverage { border-collapse: collapse; margin:0; padding: 0 } + +table.coverage td { + margin: 0; + padding: 0; + color: #111; + vertical-align: top; +} +table.coverage td.line-count { + width: 50px; + text-align: right; + padding-right: 5px; +} +table.coverage td.line-coverage { + color: #777 !important; + text-align: right; + border-left: 1px solid #666; + border-right: 1px solid #666; +} + +table.coverage td.text { +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 40px; +} +table.coverage td span.cline-neutral { + background: #eee; +} +table.coverage td span.cline-yes { + background: #b5d592; + color: #999; +} +table.coverage td span.cline-no { + background: #fc8c84; +} + +.cstat-yes { color: #111; } +.cstat-no { background: #fc8c84; color: #111; } +.fstat-no { background: #ffc520; color: #111 !important; } +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +.missing-if-branch { + display: inline-block; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: black; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} + +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} + +.entity, .metric { font-weight: bold; } +.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; } +.metric small { font-size: 80%; font-weight: normal; color: #666; } + +div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; } +div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; } +div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; } +div.coverage-summary th.file { border-right: none !important; } +div.coverage-summary th.pic { border-left: none !important; text-align: right; } +div.coverage-summary th.pct { border-right: none !important; } +div.coverage-summary th.abs { border-left: none !important; text-align: right; } +div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; } +div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; } +div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; } +div.coverage-summary td.pic { min-width: 120px !important; } +div.coverage-summary a:link { text-decoration: none; color: #000; } +div.coverage-summary a:visited { text-decoration: none; color: #777; } +div.coverage-summary a:hover { text-decoration: underline; } +div.coverage-summary tfoot td { border-top: 1px solid #666; } + +div.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +div.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +div.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} + +.high { background: #b5d592 !important; } +.medium { background: #ffe87c !important; } +.low { background: #fc8c84 !important; } + +span.cover-fill, span.cover-empty { + display:inline-block; + border:1px solid #444; + background: white; + height: 12px; +} +span.cover-fill { + background: #ccc; + border-right: 1px solid #444; +} +span.cover-empty { + background: white; + border-left: none; +} +span.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } diff --git a/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/index.html b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/index.html new file mode 100644 index 00000000..c1ac2577 --- /dev/null +++ b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/index.html @@ -0,0 +1,60 @@ + + + + Code coverage report for All files + + + + + + +
+

Code coverage report for All files

+

+ Statements: 100% (0 / 0)      + Branches: 100% (0 / 0)      + Functions: 100% (0 / 0)      + Lines: 100% (0 / 0)      + Ignored: none      +

+
+
+
+
+ + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
+
+
+ + + + + + diff --git a/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.css b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.js b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.js new file mode 100644 index 00000000..ef51e038 --- /dev/null +++ b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/sort-arrow-sprite.png b/coverage/Opera 31.0.1889 (Mac OS X 10.9.5)/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + el = getNthColumn(i).querySelector('.sorter'); + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/base.css b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/base.css new file mode 100644 index 00000000..a9d48374 --- /dev/null +++ b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/base.css @@ -0,0 +1,182 @@ +body, html { + margin:0; padding: 0; +} +body { + font-family: Helvetica Neue, Helvetica,Arial; + font-size: 10pt; +} +div.header, div.footer { + background: #eee; + padding: 1em; +} +div.header { + z-index: 100; + position: fixed; + top: 0; + border-bottom: 1px solid #666; + width: 100%; +} +div.footer { + border-top: 1px solid #666; +} +div.body { + margin-top: 10em; +} +div.meta { + font-size: 90%; + text-align: center; +} +h1, h2, h3 { + font-weight: normal; +} +h1 { + font-size: 12pt; +} +h2 { + font-size: 10pt; +} +pre { + font-family: Consolas, Menlo, Monaco, monospace; + margin: 0; + padding: 0; + line-height: 14px; + font-size: 14px; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} + +div.path { font-size: 110%; } +div.path a:link, div.path a:visited { color: #000; } +table.coverage { border-collapse: collapse; margin:0; padding: 0 } + +table.coverage td { + margin: 0; + padding: 0; + color: #111; + vertical-align: top; +} +table.coverage td.line-count { + width: 50px; + text-align: right; + padding-right: 5px; +} +table.coverage td.line-coverage { + color: #777 !important; + text-align: right; + border-left: 1px solid #666; + border-right: 1px solid #666; +} + +table.coverage td.text { +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 40px; +} +table.coverage td span.cline-neutral { + background: #eee; +} +table.coverage td span.cline-yes { + background: #b5d592; + color: #999; +} +table.coverage td span.cline-no { + background: #fc8c84; +} + +.cstat-yes { color: #111; } +.cstat-no { background: #fc8c84; color: #111; } +.fstat-no { background: #ffc520; color: #111 !important; } +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +.missing-if-branch { + display: inline-block; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: black; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} + +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} + +.entity, .metric { font-weight: bold; } +.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; } +.metric small { font-size: 80%; font-weight: normal; color: #666; } + +div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; } +div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; } +div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; } +div.coverage-summary th.file { border-right: none !important; } +div.coverage-summary th.pic { border-left: none !important; text-align: right; } +div.coverage-summary th.pct { border-right: none !important; } +div.coverage-summary th.abs { border-left: none !important; text-align: right; } +div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; } +div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; } +div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; } +div.coverage-summary td.pic { min-width: 120px !important; } +div.coverage-summary a:link { text-decoration: none; color: #000; } +div.coverage-summary a:visited { text-decoration: none; color: #777; } +div.coverage-summary a:hover { text-decoration: underline; } +div.coverage-summary tfoot td { border-top: 1px solid #666; } + +div.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +div.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +div.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} + +.high { background: #b5d592 !important; } +.medium { background: #ffe87c !important; } +.low { background: #fc8c84 !important; } + +span.cover-fill, span.cover-empty { + display:inline-block; + border:1px solid #444; + background: white; + height: 12px; +} +span.cover-fill { + background: #ccc; + border-right: 1px solid #444; +} +span.cover-empty { + background: white; + border-left: none; +} +span.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } diff --git a/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/index.html b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/index.html new file mode 100644 index 00000000..c1ac2577 --- /dev/null +++ b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/index.html @@ -0,0 +1,60 @@ + + + + Code coverage report for All files + + + + + + +
+

Code coverage report for All files

+

+ Statements: 100% (0 / 0)      + Branches: 100% (0 / 0)      + Functions: 100% (0 / 0)      + Lines: 100% (0 / 0)      + Ignored: none      +

+
+
+
+
+ + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
+
+
+ + + + + + diff --git a/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.css b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.js b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.js new file mode 100644 index 00000000..ef51e038 --- /dev/null +++ b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/sort-arrow-sprite.png b/coverage/PhantomJS 1.9.8 (Mac OS X 0.0.0)/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + el = getNthColumn(i).querySelector('.sorter'); + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/gruntfile.js b/gruntfile.js index bd5719ba..4a7f0a51 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -151,7 +151,19 @@ module.exports = function(grunt) { unit: { configFile: 'karma.conf.js' } - } + }, + // protractor: { + // options: { + // configFile: 'protractor.conf.js', + // keepAlive: true, + // noColor: false + // }, + // e2e: { + // options: { + // args: {} // Target-specific arguments + // } + // } + // }, }); // Load NPM tasks diff --git a/karma.conf.js b/karma.conf.js index effde2de..50e408dd 100755 --- a/karma.conf.js +++ b/karma.conf.js @@ -8,8 +8,6 @@ var applicationConfiguration = require('./config/config'), var bowerDep = bowerFiles('**/**.js'); -console.log(bowerDep); - // Karma configuration module.exports = function(config) { config.set({ @@ -21,7 +19,12 @@ module.exports = function(config) { // Test results reporter to use // Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' - reporters: ['progress'], + reporters: ['mocha', 'html', 'progress'], + + // plugins: [ + // 'karma-jasmine', + // 'karma-mocha-reporter', + // ], // Web server port port: 9876, @@ -51,6 +54,6 @@ module.exports = function(config) { // Continuous Integration mode // If true, it capture browsers, run tests and exit - singleRun: true + singleRun: false }); }; diff --git a/package.json b/package.json index e55d8b35..83ec730a 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,9 @@ }, "devDependencies": { "karma-chrome-launcher": "^0.1.12", - "karma-jasmine": "^0.2.3" + "karma-jasmine": "^0.2.3", + "karma-jasmine-html-reporter": "^0.1.8", + "karma-mocha-reporter": "^1.1.1", + "node-mandrill": "^1.0.1" } } diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 00000000..72d71fc9 --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,6 @@ +'use strict'; + +// Protractor configuration +exports.config = { + specs: ['modules/*/tests/e2e/*.js'] +}; \ No newline at end of file diff --git a/public/dist/application.js b/public/dist/application.js index 4cabfdba..51ce5695 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -142,14 +142,10 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider', ]); 'use strict'; -angular.module('core').controller('HeaderController', ['$rootScope','$scope','Menus', '$state', 'Auth', 'User', +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; - // if(!$scope.user || !$scope.user.username){ - // $scope.user = $rootScope.user = User.getCurrent(); - // $scope.authentication.currentUser = $rootScope.authentication.currentUser = $scope.user; - // } $rootScope.languages = $scope.languages = ['english', 'french', 'spanish']; @@ -426,7 +422,7 @@ angular.module('forms').config(['$stateProvider', }). state('viewForm', { url: '/forms/:formId/admin', - templateUrl: 'modules/forms/views/view-form.client.view.html', + templateUrl: 'modules/forms/views/admin-form.client.view.html', data: { permissions: [ 'editForm' ] } @@ -442,6 +438,121 @@ angular.module('forms').config(['$stateProvider', ]); 'use strict'; +// Forms controller +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.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 + }); + }; + + /* + ** DeleteModal Functions + */ + $scope.openDeleteModal = function() { + + deleteModal = $modal.open({ + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + controller: 'AdminFormController', + }); + }; + $scope.cancelDeleteModal = function(){ + if(deleteModal){ + deleteModal.dismiss('cancel'); + } + }; + + // Remove existing Form + $scope.remove = function(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(){ + + }); + } + }; + + + // Update existing Form + $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); + }).catch(function(response){ + 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); + }); + } + }; + + } +]); +'use strict'; + // Forms controller angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm','$http', function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) { @@ -566,253 +677,6 @@ angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScop ]); 'use strict'; -// Forms controller -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; - $scope.table = { - masterChecker: false, - rows: [] - }; - - // Find a specific Form - $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 - }); - }; - - /* - * 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(){ - // console.log('exportSelectedSubmissions'); - // var export_ids = _.chain($scope.table.rows).filter(function(row){ - // return !!row.selected; - // }).pluck('_id').value(); - - var blob = new Blob([document.getElementById('table-submission-data').innerHTM], { - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8" - }); - saveAs(blob, $scope.myform.title+'_export_'+Date.now()+".xls"); - }; - - - //Fetch and display submissions of Form - $scope.showSubmissions = function(){ - $scope.viewSubmissions = true; - - $http.get('/forms/'+$scope.myform._id+'/submissions') - .success(function(data, status, headers){ - // console.log(data[0].form_fields); - - var _data = []; - for(var i=0; i 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(){ - - }); - } - }; - - - // Update existing Form - $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); - }).catch(function(response){ - 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); - }); - } - }; - - } -]); -'use strict'; - angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', function($rootScope, $timeout) { return { @@ -952,325 +816,6 @@ 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.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.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); - // for(var i = 0; i < $scope.myform.form_fields.length; i++){ - // if($scope.myform.form_fields[i].field_id === field.field_id){ - - // break; - // } - // } - }; - - - /* - ** StartPage Button Methods - */ - - // add new Button to the field - $scope.addButton = function (Button){ - - var lastButtonID = 0; - - if($scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1]) - lastButtonID = $scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1].button_id; - - // put new option into fieldOptions array - Button.backgroundColor = '#5bc0de'; - Button.button_id = lastButtonID; - Button.color = '#ffffff'; - - - $scope.myform.StartPage.buttons.push(Button); - }; - - // delete particular option - $scope.deleteButton = function (button_index){ - $scope.myform.StartPage.buttons.splice(button_index, 1); - }; - - /* - ** 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 { @@ -1385,14 +930,6 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root }; }]); 'use strict'; -angular.module('forms').directive('formLocator', function() { - return { - link: function(scope) { - scope.$emit('formLocator'); - } - }; -}); -'use strict'; angular.module('forms').directive('onFinishRender', function ($rootScope, $timeout) { return { @@ -1428,7 +965,7 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', '$filter', '$rootScope', function ($http, $timeout, timeCounter, Auth, $filter, $rootScope) { return { - templateUrl: './modules/forms/views/directiveViews/form/submit-form.html', + templateUrl: './modules/forms/views/directiveViews/form/submit-form.client.view.html', restrict: 'E', scope: { form:'=' @@ -1497,6 +1034,12 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo angular.module('forms').directive('tableDirective', ['$http', '$timeout', 'Auth', function ($http, $timeout, Auth) { return { + templateUrl: './modules/forms/views/directiveViews/table/table.html', + restrict: 'E', + scope: { + rows:'=', + extras:'=', + }, controller: function($scope){ $scope.toggleChecker = function(checked) { @@ -1513,13 +1056,10 @@ angular.module('forms').directive('tableDirective', ['$http', '$timeout', 'Auth' $scope.gridOptions.$gridScope.checker = allChecked; }; + + }, - templateUrl: './modules/forms/views/directiveViews/table/table.html', - restrict: 'E', - scope: { - rows:'=', - extras:'=', - } + }; } ]); @@ -2047,8 +1587,7 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro 'use strict'; angular.module('users').factory('Auth', function($window) { - var userState = - { + var userState = { isLoggedIn: false }; diff --git a/public/dist/application.min.js b/public/dist/application.min.js index e64a9cf2..2bdbc2cf 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("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.myform=form,!$scope.myform.isLive&&$rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$scope.myform.isLive||$state.go("access_denied"),console.log("$rootScope.hideNav: "+$rootScope.hideNav),console.log("$scope.form.isLive: "+$scope.myform.isLive)},function(error){$scope.error=error.message,console.log("ERROR: "+error.message),$state.go("access_denied")})}]),angular.module("forms").controller("ViewFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){var deleteModal;$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.viewSubmissions=!1,$scope.table={masterChecker:!1,rows:[]},$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.isAtLeastOneChecked=function(){for(var i=0;i<$scope.table.rows.length;i++)if($scope.table.rows[i].selected)return!0;return!1},$scope.toggleAllCheckers=function(){for(var i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected=$scope.table.masterChecker},$scope.toggleObjSelection=function($event,description){$event.stopPropagation()},$scope.rowClicked=function(row_index){$scope.table.rows[row_index].selected=!$scope.table.rows[row_index].selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();$http({url:"/forms/"+$scope.myform._id+"/submissions",method:"DELETE",data:{deleted_submissions:delete_ids},headers:{"Content-Type":"application/json;charset=utf-8"}}).success(function(data,status,headers){for(var tmpArray=[],i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected||tmpArray.push($scope.table.rows[i]);console.log(tmpArray),$scope.table.rows=tmpArray}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$scope.exportSelectedSubmissions=function(){var blob=(_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value(),new Blob([document.getElementById("table-submission-data").innerHTM],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"}));saveAs(blob,$scope.form.title+"_export_"+Date.now()+".xls")},$scope.showSubmissions=function(){$scope.viewSubmissions=!0,$http.get("/forms/"+$scope.myform._id+"/submissions").success(function(data,status,headers){for(var _data=[],i=0;i0&&($scope.myforms=_.filter($scope.myforms,function(myform){return myform._id!==form._id}))}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})["finally"](function(){})}},$scope.update=$rootScope.update=function(immediate,cb){console.log("immediate: "+immediate);var continueUpdate=!0;if(immediate&&(continueUpdate=!$rootScope.saveInProgress),continueUpdate){console.log("begin updating form");var err=null;immediate&&($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data,console.log(response.data)})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),console.log(response.data),err=response.data})["finally"](function(){console.log("finished updating"),immediate&&($rootScope.saveInProgress=!1),cb(err)})}}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",controller:function($scope){},link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var updateFields=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!1,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&updateFields()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),updateFields()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("changeFocus",function(){return{scope:{focusDownId:"@",focusUpId:"@"},link:function(scope,elem,attrs){scope.focusUp=function(){scope.$first||(console.log("focusUp"),elem[0].previousElementSibling.find("input").focus()),scope.apply()},scope.focusDown=function(){scope.$last||elem[0].nextElementSibling.focus(),scope.apply()},angular.element("#"+scope.focusDownId).bind("click",function(){scope.focusDown()}),angular.element("#"+scope.focusUpId).bind("click",function(){scope.focusUp()})}}}),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/configure-form.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:function($scope){$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages;var _current_upload=null;$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update;$scope.pdfFields;$scope.cancelUpload=function(){_current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(files){if(files&&files.length){var file=files[0];console.log(file),_current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),console.log($scope.myform.pdf),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","timeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/edit-form.html",restrict:"E",scope:{myform:"="},controller:function($scope){$scope.addField={},$scope.addField.types=FormFields.fields,$scope.addField.types.forEach(function(type){return type.lastAddedID=1,type}),$scope.accordion={},$scope.accordion.oneAtATime=!0,$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},$scope.addNewField=function(addOrReturn,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1};return console.log("\n\n---------\nAdded field CLIENT"),console.log(newField),addOrReturn?void $scope.myform.form_fields.push(newField):newField},$scope.deleteField=function(hashKey){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].$$hashKey===hashKey){$scope.myform.form_fields.splice(i,1);break}},$scope.duplicateField=function(field_index){console.log("field_index: "+field_index);var field=$scope.addNewField(!1,$scope.myform.form_fields[field_index].fieldType);field.title=$scope.myform.form_fields[field_index].title,console.log($scope.myform.form_fields[field_index]),$scope.myform.form_fields.splice(field_index+1,0,field)},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="./modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType?scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0}:"natural"===scope.field.fieldType&&(scope.field.fieldMatchValue="",scope.$watch("scope.field",function(newField,oldField){}));var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data),$compile(element.contents())(scope)})};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("formLocator",function(){return{link:function(scope){scope.$emit("formLocator")}}}),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$last?scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})}):$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")})}}}}),angular.module("forms").directive("formDirective",["$http","$timeout","timeCounter","Auth","$filter","$rootScope",function($http,$timeout,timeCounter,Auth,$filter,$rootScope){return{templateUrl:"./modules/forms/views/directiveViews/form/submit-form.html",restrict:"E",scope:{form:"="},controller:function($scope){angular.element(document).ready(function(){$scope.selected=null,$scope.startPage=!0,$rootScope.setActiveField=function(field_id){console.log("form field clicked: "+field_id),$scope.selected=field_id,console.log($scope.selected)},$scope.hideOverlay=function(){$scope.selected=null,console.log($scope.myForm)},$scope.submit=function(){var _timeElapsed=timeCounter.stopClock();$scope.form.timeElapsed=_timeElapsed,$scope.form.percentageComplete=$filter("formValidity")($scope.form)/$scope.form.visible_form_fields.length*100,console.log($scope.form.percentageComplete),$scope.authentication=Auth,$scope.submitPromise=$http.post("/forms/"+$scope.form._id,$scope.form).success(function(data,status,headers){console.log("form submitted successfully"),$scope.form.submitted=!0}).error(function(error){console.log(error),$scope.error=error.message})},$scope.exitStartPage=function(){$scope.startPage=!1},$scope.reloadForm=function(){timeCounter.stopClock(),timeCounter.startClock(),$scope.form.submitted=!1,$scope.form.form_fields=_.chain($scope.form.form_fields).map(function(field){return field.fieldValue="",field}).value()}})}}}]),angular.module("forms").directive("tableDirective",["$http","$timeout","Auth",function($http,$timeout,Auth){return{controller:function($scope){$scope.toggleChecker=function(checked){for(var rows=$scope.gridOptions.$gridScope.renderedRows,allChecked=!0,r=0;ri;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +"use strict";var ApplicationConfiguration=function(){var applicationModuleName="medform",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||(event.preventDefault(),$state.go("home"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null===permissions||authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$state.go("access_denied")))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/view-form.client.view.html",data:{permissions:["editForm"]}}).state("viewPublicForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/view-public-form.client.view.html",data:{hideNav:!0}})}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$rootScope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$rootScope.showCreateModal||($rootScope.showCreateModal=!0)},$scope.closeCreateModal=function(){$rootScope.showCreateModal&&($rootScope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicate=function(form,form_index){delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form duplicated"),$scope.myforms.splice(form_index,0,data)}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.createNew=function(){var form={};form.title=$scope.myform.name.$modelValue,form.language=$scope.myform.language.$modelValue,$rootScope.showCreateModal=!0,$scope.myform.$valid&&$scope.myform.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form created"),$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeFromList=function(deleted_form_id){console.log("Remove existing form"),$http["delete"]("/forms/"+deleted_form_id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.length>0&&($scope.myforms=_.filter($scope.myforms,function(myform){return myform._id!==deleted_form_id}))}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.myform=form,!$scope.myform.isLive&&$rootScope.authentication.isAuthenticated()?$rootScope.hideNav=!1:$scope.myform.isLive||$state.go("access_denied"),console.log("$rootScope.hideNav: "+$rootScope.hideNav),console.log("$scope.form.isLive: "+$scope.myform.isLive)},function(error){$scope.error=error.message,console.log("ERROR: "+error.message),$state.go("access_denied")})}]),angular.module("forms").controller("ViewFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){var deleteModal;$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.viewSubmissions=!1,$scope.table={masterChecker:!1,rows:[]},$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.isAtLeastOneChecked=function(){for(var i=0;i<$scope.table.rows.length;i++)if($scope.table.rows[i].selected)return!0;return!1},$scope.toggleAllCheckers=function(){for(var i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected=$scope.table.masterChecker},$scope.toggleObjSelection=function($event,description){$event.stopPropagation()},$scope.rowClicked=function(row_index){$scope.table.rows[row_index].selected=!$scope.table.rows[row_index].selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();$http({url:"/forms/"+$scope.myform._id+"/submissions",method:"DELETE",data:{deleted_submissions:delete_ids},headers:{"Content-Type":"application/json;charset=utf-8"}}).success(function(data,status,headers){for(var tmpArray=[],i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected||tmpArray.push($scope.table.rows[i]);console.log(tmpArray),$scope.table.rows=tmpArray}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$scope.exportSubmissions=function(){var blob=new Blob([document.getElementById("table-submission-data").innerHTM],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"});saveAs(blob,$scope.myform.title+"_export_"+Date.now()+".xls")},$scope.showSubmissions=function(){$scope.viewSubmissions=!0,$http.get("/forms/"+$scope.myform._id+"/submissions").success(function(data,status,headers){for(var _data=[],i=0;i0&&($scope.myforms=_.filter($scope.myforms,function(myform){return myform._id!==form._id}))}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})["finally"](function(){})}},$scope.update=$rootScope.update=function(immediate,cb){console.log("immediate: "+immediate);var continueUpdate=!0;if(immediate&&(continueUpdate=!$rootScope.saveInProgress),continueUpdate){console.log("begin updating form");var err=null;immediate&&($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data,console.log(response.data)})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),console.log(response.data),err=response.data})["finally"](function(){console.log("finished updating"),immediate&&($rootScope.saveInProgress=!1),cb(err)})}}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",controller:function($scope){},link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!1,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("changeFocus",function(){return{scope:{focusDownId:"@",focusUpId:"@"},link:function(scope,elem,attrs){scope.focusUp=function(){scope.$first||(console.log("focusUp"),elem[0].previousElementSibling.find("input").focus()),scope.apply()},scope.focusDown=function(){scope.$last||elem[0].nextElementSibling.focus(),scope.apply()},angular.element("#"+scope.focusDownId).bind("click",function(){scope.focusDown()}),angular.element("#"+scope.focusUpId).bind("click",function(){scope.focusUp()})}}}),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/configure-form.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:function($scope){$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages;var _current_upload=null;$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update;$scope.pdfFields;$scope.cancelUpload=function(){_current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(files){if(files&&files.length){var file=files[0];console.log(file),_current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),console.log($scope.myform.pdf),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","timeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/edit-form.html",restrict:"E",scope:{myform:"="},controller:function($scope){$scope.addField={},$scope.addField.types=FormFields.fields,$scope.addField.types.forEach(function(type){return type.lastAddedID=1,type}),$scope.accordion={},$scope.accordion.oneAtATime=!0,$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},$scope.addNewField=function(addOrReturn,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1};return console.log("\n\n---------\nAdded field CLIENT"),console.log(newField),addOrReturn?void $scope.myform.form_fields.push(newField):newField},$scope.deleteField=function(hashKey){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].$$hashKey===hashKey){$scope.myform.form_fields.splice(i,1);break}},$scope.duplicateField=function(field_index){console.log("field_index: "+field_index);var field=$scope.addNewField(!1,$scope.myform.form_fields[field_index].fieldType);field.title=$scope.myform.form_fields[field_index].title,console.log($scope.myform.form_fields[field_index]),$scope.myform.form_fields.splice(field_index+1,0,field)},$scope.addButton=function(Button){var lastButtonID=0;$scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1]&&(lastButtonID=$scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1].button_id),Button.backgroundColor="#5bc0de",Button.button_id=lastButtonID,Button.color="#ffffff",$scope.myform.StartPage.buttons.push(Button)},$scope.deleteButton=function(button_index){$scope.myform.StartPage.buttons.splice(button_index,1)},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="./modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType?scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0}:"natural"===scope.field.fieldType&&(scope.field.fieldMatchValue="",scope.$watch("scope.field",function(newField,oldField){}));var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data),$compile(element.contents())(scope)})};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("formLocator",function(){return{link:function(scope){scope.$emit("formLocator")}}}),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$last?scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})}):$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")})}}}}),angular.module("forms").directive("formDirective",["$http","$timeout","timeCounter","Auth","$filter","$rootScope",function($http,$timeout,timeCounter,Auth,$filter,$rootScope){return{templateUrl:"./modules/forms/views/directiveViews/form/submit-form.html",restrict:"E",scope:{form:"="},controller:function($scope){angular.element(document).ready(function(){$scope.selected=null,timeCounter.startClock(),$rootScope.setActiveField=function(field_id){console.log("form field clicked: "+field_id),$scope.selected=field_id,console.log($scope.selected)},$scope.hideOverlay=function(){$scope.selected=null,console.log($scope.myForm)},$scope.submit=function(){var _timeElapsed=timeCounter.stopClock();$scope.form.timeElapsed=_timeElapsed,$scope.form.percentageComplete=$filter("formValidity")($scope.form)/$scope.form.visible_form_fields.length*100,console.log($scope.form.percentageComplete),$scope.authentication=Auth,$scope.submitPromise=$http.post("/forms/"+$scope.form._id,$scope.form).success(function(data,status,headers){console.log("form submitted successfully"),$scope.form.submitted=!0}).error(function(error){console.log(error),$scope.error=error.message})},$scope.exitStartPage=function(){$scope.form.startPage.showStart=!1},$scope.reloadForm=function(){timeCounter.stopClock(),timeCounter.startClock(),$scope.form.submitted=!1,$scope.form.form_fields=_.chain($scope.form.form_fields).map(function(field){return field.fieldValue="",field}).value()}})}}}]),angular.module("forms").directive("tableDirective",["$http","$timeout","Auth",function($http,$timeout,Auth){return{controller:function($scope){$scope.toggleChecker=function(checked){for(var rows=$scope.gridOptions.$gridScope.renderedRows,allChecked=!0,r=0;ri;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/core/controllers/header.client.controller.js b/public/modules/core/controllers/header.client.controller.js index ee292952..77e01283 100755 --- a/public/modules/core/controllers/header.client.controller.js +++ b/public/modules/core/controllers/header.client.controller.js @@ -1,13 +1,9 @@ 'use strict'; -angular.module('core').controller('HeaderController', ['$rootScope','$scope','Menus', '$state', 'Auth', 'User', +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; - // if(!$scope.user || !$scope.user.username){ - // $scope.user = $rootScope.user = User.getCurrent(); - // $scope.authentication.currentUser = $rootScope.authentication.currentUser = $scope.user; - // } $rootScope.languages = $scope.languages = ['english', 'french', 'spanish']; diff --git a/public/modules/core/tests/header.client.controller.test.js b/public/modules/core/tests/header.client.controller.test.js index 76ee4fb4..962575bc 100755 --- a/public/modules/core/tests/header.client.controller.test.js +++ b/public/modules/core/tests/header.client.controller.test.js @@ -1,24 +1,24 @@ -'use strict'; +// 'use strict'; -(function() { - describe('HeaderController', function() { - //Initialize global variables - var scope, - HeaderController; +// (function() { +// describe('HeaderController', function() { +// //Initialize global variables +// var scope, +// HeaderController; - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); +// // Load the main application module +// beforeEach(module(ApplicationConfiguration.applicationModuleName)); - beforeEach(inject(function($controller, $rootScope) { - scope = $rootScope.$new(); +// beforeEach(inject(function($controller, $rootScope) { +// scope = $rootScope.$new(); - HeaderController = $controller('HeaderController', { - $scope: scope - }); - })); +// HeaderController = $controller('HeaderController', { +// $scope: scope +// }); +// })); - it('should expose the authentication service', function() { - expect(scope.authentication).toBeTruthy(); - }); - }); -})(); \ No newline at end of file +// it('should expose the authentication service', function() { +// expect(scope.authentication).toBeTruthy(); +// }); +// }); +// })(); \ No newline at end of file diff --git a/public/modules/core/tests/home.client.controller.test.js b/public/modules/core/tests/home.client.controller.test.js index a5b1a566..8b6deaa2 100755 --- a/public/modules/core/tests/home.client.controller.test.js +++ b/public/modules/core/tests/home.client.controller.test.js @@ -1,24 +1,24 @@ -'use strict'; +// 'use strict'; -(function() { - describe('HomeController', function() { - //Initialize global variables - var scope, - HomeController; +// (function() { +// describe('HomeController', function() { +// //Initialize global variables +// var scope, +// HomeController; - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); +// // Load the main application module +// beforeEach(module(ApplicationConfiguration.applicationModuleName)); - beforeEach(inject(function($controller, $rootScope) { - scope = $rootScope.$new(); +// beforeEach(inject(function($controller, $rootScope) { +// scope = $rootScope.$new(); - HomeController = $controller('HomeController', { - $scope: scope - }); - })); +// HomeController = $controller('HomeController', { +// $scope: scope +// }); +// })); - it('should expose the authentication service', function() { - expect(scope.authentication).toBeTruthy(); - }); - }); -})(); \ No newline at end of file +// it('should expose the authentication service', function() { +// expect(scope.authentication).toBeTruthy(); +// }); +// }); +// })(); \ No newline at end of file diff --git a/public/modules/forms/config/forms.client.routes.js b/public/modules/forms/config/forms.client.routes.js index 186be1be..87f062bf 100644 --- a/public/modules/forms/config/forms.client.routes.js +++ b/public/modules/forms/config/forms.client.routes.js @@ -15,7 +15,7 @@ angular.module('forms').config(['$stateProvider', }). state('viewForm', { url: '/forms/:formId/admin', - templateUrl: 'modules/forms/views/view-form.client.view.html', + templateUrl: 'modules/forms/views/admin-form.client.view.html', data: { permissions: [ 'editForm' ] } diff --git a/public/modules/forms/controllers/admin-form.client.controller.js b/public/modules/forms/controllers/admin-form.client.controller.js new file mode 100644 index 00000000..8f442342 --- /dev/null +++ b/public/modules/forms/controllers/admin-form.client.controller.js @@ -0,0 +1,115 @@ +'use strict'; + +// Forms controller +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.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 + }); + }; + + /* + ** DeleteModal Functions + */ + $scope.openDeleteModal = function(){ + + deleteModal = $modal.open({ + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + controller: 'AdminFormController', + }); + }; + $scope.cancelDeleteModal = function(){ + if(deleteModal){ + deleteModal.dismiss('cancel'); + } + }; + + // Remove existing Form + $scope.remove = function(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(){ + + }); + } + }; + + + // Update existing Form + $scope.update = $rootScope.update = function(shouldUpdateNow, cb){ + // console.log('shouldUpdateNow: '+shouldUpdateNow); + var continueUpdate = true; + if(shouldUpdateNow){ + continueUpdate = !$rootScope.saveInProgress; + } + + if(continueUpdate){ + console.log('begin updating form'); + var err = null; + + if(shouldUpdateNow){ $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); + }).catch(function(response){ + console.log('Error occured during form UPDATE.\n'); + console.log(response.data); + err = response.data; + }).finally(function() { + console.log('finished updating'); + if(shouldUpdateNow){$rootScope.saveInProgress = false; } + cb(err); + }); + } + }; + + } +]); \ 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 deleted file mode 100644 index 92d60a98..00000000 --- a/public/modules/forms/controllers/view-form.client.controller.js +++ /dev/null @@ -1,247 +0,0 @@ -'use strict'; - -// Forms controller -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; - $scope.table = { - masterChecker: false, - rows: [] - }; - - // Find a specific Form - $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 - }); - }; - - /* - * 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(){ - // console.log('exportSelectedSubmissions'); - // var export_ids = _.chain($scope.table.rows).filter(function(row){ - // return !!row.selected; - // }).pluck('_id').value(); - - var blob = new Blob([document.getElementById('table-submission-data').innerHTM], { - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8" - }); - saveAs(blob, $scope.myform.title+'_export_'+Date.now()+".xls"); - }; - - - //Fetch and display submissions of Form - $scope.showSubmissions = function(){ - $scope.viewSubmissions = true; - - $http.get('/forms/'+$scope.myform._id+'/submissions') - .success(function(data, status, headers){ - // console.log(data[0].form_fields); - - var _data = []; - for(var i=0; i 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(){ - - }); - } - }; - - - // Update existing Form - $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); - }).catch(function(response){ - 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); - }); - } - }; - - } -]); \ No newline at end of file diff --git a/public/modules/forms/css/form.css b/public/modules/forms/css/form.css index d702c050..142f1fec 100644 --- a/public/modules/forms/css/form.css +++ b/public/modules/forms/css/form.css @@ -1,3 +1,15 @@ +.panel-default.startPage { + + /*background-color: #eee;*/ + border-style: dashed; + border-color: #a9a9a9; + border-width:3px; +} + +section.content p { + word-break: break-all; +} + .btn { border: 1px solid #c6c6c6!important; } diff --git a/public/modules/forms/directives/configure-form.client.directive.js b/public/modules/forms/directives/configure-form.client.directive.js index ce9ef08d..22d54b04 100644 --- a/public/modules/forms/directives/configure-form.client.directive.js +++ b/public/modules/forms/directives/configure-form.client.directive.js @@ -3,7 +3,7 @@ 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', + templateUrl: './modules/forms/views/directiveViews/form/configure-form.client.view.html', restrict: 'E', scope: { myform:'=', diff --git a/public/modules/forms/directives/edit-form.client.directive.js b/public/modules/forms/directives/edit-form.client.directive.js index f809a381..5d114710 100644 --- a/public/modules/forms/directives/edit-form.client.directive.js +++ b/public/modules/forms/directives/edit-form.client.directive.js @@ -4,7 +4,7 @@ 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', + templateUrl: './modules/forms/views/directiveViews/form/edit-form.client.view.html', restrict: 'E', scope: { myform:'=', @@ -142,44 +142,43 @@ angular.module('forms') 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); - // for(var i = 0; i < $scope.myform.form_fields.length; i++){ - // if($scope.myform.form_fields[i].field_id === field.field_id){ - - // break; - // } - // } + }; /* - ** StartPage Button Methods + ** startPage Button Methods */ - // add new Button to the field - $scope.addButton = function (Button){ + // add new Button to the startPage/EndPage + $scope.addButton = function (newButtons){ - var lastButtonID = 0; + var newButton = {}; + newButton.bgColor = '#ddd'; + newButton.color = '#ffffff'; + newButton.text = 'Button'; - if($scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1]) - lastButtonID = $scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1].button_id; - - // put new option into fieldOptions array - Button.backgroundColor = '#5bc0de'; - Button.button_id = lastButtonID; - Button.color = '#ffffff'; - - - $scope.myform.StartPage.buttons.push(Button); + $scope.myform.startPage.buttons.push(newButton); }; - // delete particular option - $scope.deleteButton = function (button_index){ - $scope.myform.StartPage.buttons.splice(button_index, 1); + // 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 */ diff --git a/public/modules/forms/directives/form-locator.client.directive.js b/public/modules/forms/directives/form-locator.client.directive.js deleted file mode 100644 index 4b9d3c81..00000000 --- a/public/modules/forms/directives/form-locator.client.directive.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; -angular.module('forms').directive('formLocator', function() { - return { - link: function(scope) { - scope.$emit('formLocator'); - } - }; -}); \ No newline at end of file diff --git a/public/modules/forms/directives/submissions-form.client.directive.js b/public/modules/forms/directives/submissions-form.client.directive.js new file mode 100644 index 00000000..3ac82c74 --- /dev/null +++ b/public/modules/forms/directives/submissions-form.client.directive.js @@ -0,0 +1,153 @@ +'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'; +// // inject allows you to use AngularJS dependency injection +// // to retrieve and use other services +// inject(function($compile) { +// var form = $compile(tpl)(scope); +// elm = form.find('div'); +// }); +// // $digest is necessary to finalize the directive generation +// scope.$digest(); +// } + +// describe('initialisation', function() { +// // before each test in this block, generates a fresh directive +// beforeEach(function() { +// compileDirective(); +// }); +// // a single test example, check the produced DOM +// it('should produce 2 buttons and a div', function() { +// expect(elm.find('button').length).toEqual(2); +// expect(elm.find('div').length).toEqual(1); +// }); +// it('should check validity on init', function() { +// expect(scope.form.$valid).toBeTruthy(); +// }); +// }); + +// it('$scope.find() should create an array with at least one article object fetched from XHR', inject(function(Forms) { + +// })); + +// }); +// }()); \ No newline at end of file diff --git a/public/modules/forms/tests/view-from.client.controller.test.js b/public/modules/forms/tests/view-from.client.controller.test.js deleted file mode 100644 index 1369a227..00000000 --- a/public/modules/forms/tests/view-from.client.controller.test.js +++ /dev/null @@ -1,170 +0,0 @@ -// 'use strict'; - -// (function() { -// // Forms Controller Spec -// describe('ViewForm Controller Tests', function() { -// // Initialize global variables -// var ViewFormController, -// scope, -// $httpBackend, -// $stateParams, -// $location; - -// // The $resource service augments the response object with methods for updating and deleting the resource. -// // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match -// // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher. -// // When the toEqualData matcher compares two objects, it takes only object properties into -// // account and ignores methods. -// beforeEach(function() { -// jasmine.addMatchers({ -// toEqualData: function(util, customEqualityTesters) { -// return { -// compare: function(actual, expected) { -// return { -// pass: angular.equals(actual, expected) -// }; -// } -// }; -// } -// }); -// }); - -// // Then we can start by loading the main application module -// beforeEach(module(ApplicationConfiguration.applicationModuleName)); - -// // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). -// // This allows us to inject a service but then attach it to a variable -// // with the same name as the service. -// beforeEach(inject(function($controller, $rootScope, _$location_, _$stateParams_, _$httpBackend_) { -// // Set a new global scope -// scope = $rootScope.$new(); - -// // Point global variables to injected services -// $stateParams = _$stateParams_; -// $httpBackend = _$httpBackend_; -// $location = _$location_; - -// // Initialize the Forms controller. -// FormsController = $controller('FormsController', { -// $scope: scope -// }); -// })); - -// it('$scope.find() should create an array with at least one article object fetched from XHR', inject(function(Forms) { -// // Create sample article using the Forms service -// var sampleArticle = new Forms({ -// title: 'An Article about MEAN', -// content: 'MEAN rocks!' -// }); - -// // Create a sample Forms array that includes the new article -// var sampleForms = [sampleForm]; - -// // Set GET response -// $httpBackend.expectGET('Forms').respond(sampleForms); - -// // Run controller functionality -// scope.find(); -// $httpBackend.flush(); - -// // Test scope value -// expect(scope.Forms).toEqualData(sampleForms); -// })); - -// it('$scope.findOne() should create an array with one article object fetched from XHR using a articleId URL parameter', inject(function(Forms) { -// // Define a sample article object -// var sampleArticle = new Forms({ -// title: 'An Article about MEAN', -// content: 'MEAN rocks!' -// }); - -// // Set the URL parameter -// $stateParams.articleId = '525a8422f6d0f87f0e407a33'; - -// // Set GET response -// $httpBackend.expectGET(/Forms\/([0-9a-fA-F]{24})$/).respond(sampleArticle); - -// // Run controller functionality -// scope.findOne(); -// $httpBackend.flush(); - -// // Test scope value -// expect(scope.article).toEqualData(sampleArticle); -// })); - -// it('$scope.create() with valid form data should send a POST request with the form input values and then locate to new object URL', inject(function(Forms) { -// // Create a sample article object -// var sampleArticlePostData = new Forms({ -// title: 'An Article about MEAN', -// content: 'MEAN rocks!' -// }); - -// // Create a sample article response -// var sampleArticleResponse = new Forms({ -// _id: '525cf20451979dea2c000001', -// title: 'An Article about MEAN', -// content: 'MEAN rocks!' -// }); - -// // Fixture mock form input values -// scope.title = 'An Article about MEAN'; -// scope.content = 'MEAN rocks!'; - -// // Set POST response -// $httpBackend.expectPOST('Forms', sampleArticlePostData).respond(sampleArticleResponse); - -// // Run controller functionality -// scope.create(); -// $httpBackend.flush(); - -// // Test form inputs are reset -// expect(scope.title).toEqual(''); -// expect(scope.content).toEqual(''); - -// // Test URL redirection after the article was created -// expect($location.path()).toBe('/Forms/' + sampleArticleResponse._id); -// })); - -// it('$scope.update() should update a valid article', inject(function(Forms) { -// // Define a sample article put data -// var sampleArticlePutData = new Forms({ -// _id: '525cf20451979dea2c000001', -// title: 'An Article about MEAN', -// content: 'MEAN Rocks!' -// }); - -// // Mock article in scope -// scope.article = sampleArticlePutData; - -// // Set PUT response -// $httpBackend.expectPUT(/Forms\/([0-9a-fA-F]{24})$/).respond(); - -// // Run controller functionality -// scope.update(); -// $httpBackend.flush(); - -// // Test URL location to new object -// expect($location.path()).toBe('/Forms/' + sampleArticlePutData._id); -// })); - -// it('$scope.remove() should send a DELETE request with a valid articleId and remove the article from the scope', inject(function(Forms) { -// // Create new article object -// var sampleArticle = new Forms({ -// _id: '525a8422f6d0f87f0e407a33' -// }); - -// // Create new Forms array and include the article -// scope.Forms = [sampleArticle]; - -// // Set expected DELETE response -// $httpBackend.expectDELETE(/Forms\/([0-9a-fA-F]{24})$/).respond(204); - -// // Run controller functionality -// scope.remove(sampleArticle); -// $httpBackend.flush(); - -// // Test array after successful delete -// expect(scope.Forms.length).toBe(0); -// })); -// }); -// }()); \ No newline at end of file diff --git a/public/modules/forms/views/view-form.client.view.html b/public/modules/forms/views/admin-form.client.view.html similarity index 56% rename from public/modules/forms/views/view-form.client.view.html rename to public/modules/forms/views/admin-form.client.view.html index c67d598e..328708c6 100644 --- a/public/modules/forms/views/view-form.client.view.html +++ b/public/modules/forms/views/admin-form.client.view.html @@ -1,4 +1,4 @@ -
+