From 92c84dc500d73fb56648e319e60162518b0c100f Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Fri, 30 Oct 2015 11:40:02 -0700 Subject: [PATCH] fixed user permissions problem --- app/controllers/forms.server.controller.js | 18 +- .../users.authentication.server.controller.js | 2 +- .../users.authorization.server.controller.js | 26 +- app/models/form.server.model.js | 38 ++ app/models/form_field.server.model.js | 82 +-- app/models/form_submission.server.model.js | 4 +- app/tests/form.server.model.test.js | 4 +- app/tests/form.server.routes.test.js | 83 ++- app/tests/form_submission.model.test.js | 12 +- app/tests/user.server.routes.test.js | 223 ++++---- config/env/local.js | 17 + gruntfile.js | 2 + package.json | 6 +- public/application.js | 5 +- public/dist/application.js | 477 ++++++++++-------- public/dist/application.min.css | 2 +- public/dist/application.min.js | 4 +- .../forms/config/forms.client.routes.js | 16 +- .../admin-form.client.controller.js | 11 +- .../submit-form.client.controller.js | 48 +- public/modules/forms/css/form.css | 4 + .../directives/auto-save.client.directive.js | 55 +- .../configure-form.client.directive.js | 10 +- .../directives/edit-form.client.directive.js | 37 +- .../directives/entry_page.client.directive.js | 47 -- .../directives/field.client.directive.js | 29 +- .../on-finish-render.client.directive.js | 5 +- .../forms/services/forms.client.service.js | 1 + .../admin-form.client.controller.test.js | 6 + .../list-forms.client.controller.test.js | 8 + .../submit-form.client.controller.test.js | 16 +- .../configure-form.client.directive.test.js | 1 - .../forms/views/admin-form.client.view.html | 4 +- .../cgBusy/update-form-message-TypeB.html | 3 +- .../views/directiveViews/field/dropdown.html | 6 +- .../form/configure-form.client.view.html | 73 ++- .../form/edit-form.client.view.html | 27 +- .../forms/views/list-forms.client.view.html | 9 +- .../forms/views/submit-form.client.view.html | 2 +- server.js | 3 + 40 files changed, 814 insertions(+), 612 deletions(-) create mode 100644 config/env/local.js delete mode 100644 public/modules/forms/directives/entry_page.client.directive.js diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 30293541..bce14420 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -68,7 +68,6 @@ exports.uploadPDF = function(req, res, next) { } }; - /** * Delete a forms submissions */ @@ -89,6 +88,7 @@ exports.deleteSubmissions = function(req, res) { res.status(200).send('Form submissions successfully deleted'); }); }; + /** * Submit a form entry */ @@ -144,13 +144,13 @@ exports.createSubmission = function(req, res) { exports.listSubmissions = function(req, res) { var _form = req.form; var _user = req.user; - // console.log('listSubmissions'); + console.log('listSubmissions'); // console.log(_form); // if(_form.submissions.length){ // res.json(_form.submissions); // }else{ - FormSubmission.find({ form: req.form, admin: _user }).populate('admin', 'form').exec(function(err, _submissions) { + FormSubmission.find({ form: _form._id, admin: _user._id }).populate('admin', 'form').exec(function(err, _submissions) { if (err) { console.log(err); res.status(400).send({ @@ -201,7 +201,11 @@ exports.create = function(req, res) { * Show the current form */ exports.read = function(req, res) { - res.json(req.form); + var validUpdateTypes= Form.schema.path('plugins.oscarhost.settings.updateType').enumValues; + + var newForm = JSON.parse(JSON.stringify(req.form)); + newForm.plugins.oscarhost.settings.validUpdateTypes = validUpdateTypes; + res.json(newForm); }; /** @@ -211,7 +215,6 @@ exports.update = function(req, res) { var form = req.form; delete req.body.form.__v; delete req.body.form._id; - delete req.body.form.admin; //Unless we have 'admin' priviledges, updating form admin is disabled if(req.user.roles.indexOf('admin') === -1) delete req.body.form.admin; @@ -268,7 +271,6 @@ exports.list = function(req, res) { }); }; - /** * Form middleware */ @@ -289,13 +291,11 @@ exports.formByID = function(req, res, next, id) { }); } else { - // console.log(form.admin); - //Remove sensitive information from User object form.admin.password = undefined; form.admin.salt = undefined; form.provider = undefined; - + req.form = form; next(); } diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index 41eb0601..81b8b545 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -83,7 +83,7 @@ exports.signup = function(req, res) { }); } else { console.log('Error: Temp user already exists!'); - res.status(400).send('Error: Temp user already exists!'); + res.status(400).send({ message: 'Error: Temp user already exists!' }); } } }); diff --git a/app/controllers/users/users.authorization.server.controller.js b/app/controllers/users/users.authorization.server.controller.js index 56aa35bc..adff350b 100755 --- a/app/controllers/users/users.authorization.server.controller.js +++ b/app/controllers/users/users.authorization.server.controller.js @@ -10,13 +10,25 @@ var _ = require('lodash'), /** * User middleware */ -exports.userByID = function(req, res, next, id) { - User.findById(id).exec(function(err, user) { - if (err) return next(err); - if (!user) return next(new Error('Failed to load User ' + id)); - req.profile = user; - next(); - }); +exports.userByID = function (req, res, next, id) { + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(400).send({ + message: 'User is invalid' + }); + } + + User.findOne({ + _id: id + }).exec(function (err, user) { + if (err) { + return next(err); + } else if (!user) { + return next(new Error('Failed to load User ' + id)); + } + + req.profile = user; + next(); + }); }; /** diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 35370525..c9376666 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -154,6 +154,26 @@ var FormSchema = new Schema({ }, fieldMap: { type: Schema.Types.Mixed, + }, + validUpdateTypes: { + type: [String] + }, + validFields : { + type: [String], + default: [ + 'address', + 'city', + 'email', + 'firstName', + 'hin', + 'lastName', + 'phone', + 'postal', + 'province', + 'sex', + 'spokenLanguage', + 'title', + 'DOB'] } }, auth: { @@ -173,7 +193,25 @@ FormSchema.plugin(mUtilities.timestamp, { modifiedPath: 'lastModified', useVirtual: false }); +FormSchema.pre('save', function (next) { + var validUpdateTypes= mongoose.model('Form').schema.path('plugins.oscarhost.settings.updateType').enumValues; + this.plugins.oscarhost.settings.validUpdateTypes = validUpdateTypes; + this.plugins.oscarhost.settings.validFields = [ + 'address', + 'city', + 'email', + 'firstName', + 'hin', + 'lastName', + 'phone', + 'postal', + 'province', + 'sex', + 'spokenLanguage', + 'title', + 'DOB']; +}); //Delete template PDF of current Form FormSchema.pre('remove', function (next) { if(this.pdf && process.env.NODE_ENV === 'development'){ diff --git a/app/models/form_field.server.model.js b/app/models/form_field.server.model.js index ce4dc125..daf4647f 100644 --- a/app/models/form_field.server.model.js +++ b/app/models/form_field.server.model.js @@ -64,10 +64,34 @@ var FormFieldSchema = new Schema({ type: Boolean, default: false }, + validFieldTypes: { + type: [String] + }, fieldType: { type: String, required: true, - validate: [validateFormFieldType, 'Invalid field type'] + enum: [ + 'textfield', + 'date', + 'email', + 'link', + 'legal', + 'url', + 'textarea', + 'statement', + 'welcome', + 'thankyou', + 'file', + 'dropdown', + 'scale', + 'rating', + 'radio', + 'checkbox', + 'hidden', + 'yes_no', + 'natural', + 'number' + ], }, fieldValue: Schema.Types.Mixed }); @@ -78,61 +102,11 @@ FormFieldSchema.plugin(mUtilities.timestamp, { modifiedPath: 'lastModified', useVirtual: false }); -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; } +// FormFieldSchema.pre('init', function (next){ +// this.validFieldTypes = Field.schema.path('fieldType').enumValues; +// }); - 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; -}; mongoose.model('Field', FormFieldSchema); diff --git a/app/models/form_submission.server.model.js b/app/models/form_submission.server.model.js index 81817cdf..b20879e7 100644 --- a/app/models/form_submission.server.model.js +++ b/app/models/form_submission.server.model.js @@ -103,8 +103,6 @@ FormSubmissionSchema.plugin(mUtilities.timestamp, { useVirtual: false }); - - //Oscarhost API hook FormSubmissionSchema.pre('save', function (next) { @@ -149,7 +147,7 @@ FormSubmissionSchema.pre('save', function (next) { if(demographicsTemplate.hasOwnProperty(conversionMap[currField._id])){ _generatedDemo[propertyName] = currField.fieldValue+''; - }else if(propertyName === 'unparsedDOB'){ + }else if(propertyName === 'DOB'){ var date = new Date(currField.fieldValue); _generatedDemo['dateOfBirth'] = date.getDate()+''; _generatedDemo['yearOfBirth'] = date.getFullYear()+''; diff --git a/app/tests/form.server.model.test.js b/app/tests/form.server.model.test.js index d4b57372..60f082f4 100644 --- a/app/tests/form.server.model.test.js +++ b/app/tests/form.server.model.test.js @@ -16,7 +16,7 @@ var should = require('should'), var exampleDemo = { activeCount: 1, - unparsedDOB: '', + DOB: '', address: '880-9650 Velit. St.', chartNo: '', city: '', @@ -116,7 +116,7 @@ describe('Form Model Unit Tests:', function() { }); }); it('should be able to findOne my form without problems', function(done) { - return Form.findOne({_id: myForm._id}, function(err,form) { + return Form.findOne({title: myForm.title}).exec(function(err,form) { should.not.exist(err); should.exist(form); should.deepEqual(form.toObject(), myForm.toObject()); diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index 520ca178..c336bde5 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -17,12 +17,12 @@ var should = require('should'), /** * Globals */ -var credentials, user, _Form, userSession; +var credentials, user, myForm, userSession; /** * Form routes tests */ -describe('Form CRUD tests', function() { +describe('Form Routes Unit tests', function() { beforeEach(function(done) { @@ -48,7 +48,7 @@ describe('Form CRUD tests', function() { // Save a user to the test db and create new Form user.save(function(err) { if(err) done(err); - _Form = { + myForm = { title: 'Form Title', language: 'english', admin: user._id, @@ -78,7 +78,7 @@ describe('Form CRUD tests', function() { // Save a new Form userSession.post('/forms') - .send({form: _Form}) + .send({form: myForm}) .expect('Content-Type', /json/) .expect(200) .end(function(FormSaveErr, FormSaveRes) { @@ -109,7 +109,7 @@ describe('Form CRUD tests', function() { it('should not be able to create a Form if not logged in', function(done) { userSession.post('/forms') - .send({form: _Form}) + .send({form: myForm}) .expect(401) .end(function(FormSaveErr, FormSaveRes) { (FormSaveRes.body.message).should.equal('User is not logged in'); @@ -130,7 +130,7 @@ describe('Form CRUD tests', function() { 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 = ''; + myForm.title = ''; userSession.post('/auth/signin') .send(credentials) @@ -142,13 +142,12 @@ describe('Form CRUD tests', function() { // Save a new Form userSession.post('/forms') - .send({form: _Form}) + .send({form: myForm}) .expect(400) .end(function(FormSaveErr, FormSaveRes) { // Set message assertion (FormSaveRes.body.message).should.equal('Form Title cannot be blank'); - // Handle Form save error done(); }); }); @@ -165,7 +164,7 @@ describe('Form CRUD tests', function() { // Save a new Form userSession.post('/forms') - .send({form: _Form}) + .send({form: myForm}) .expect('Content-Type', /json/) .expect(200) .end(function(FormSaveErr, FormSaveRes) { @@ -173,11 +172,11 @@ describe('Form CRUD tests', function() { if (FormSaveErr) done(FormSaveErr); // Update Form title - _Form.title = 'WHY YOU GOTTA BE SO MEAN?'; + myForm.title = 'WHY YOU GOTTA BE SO MEAN?'; // Update an existing Form userSession.put('/forms/' + FormSaveRes.body._id) - .send({form: _Form}) + .send({form: myForm}) .expect('Content-Type', /json/) .expect(200) .end(function(FormUpdateErr, FormUpdateRes) { @@ -197,7 +196,7 @@ describe('Form CRUD tests', function() { 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); + var FormObj = new Form(myForm); // Save the Form FormObj.save(function(err, form) { @@ -210,7 +209,7 @@ describe('Form CRUD tests', function() { if(err) done(err) // Set assertion - (res.body).should.be.an.Object.with.property('title', _Form.title); + (res.body).should.be.an.Object.with.property('title', myForm.title); // Call the assertion callback done(); @@ -228,42 +227,41 @@ describe('Form CRUD tests', function() { // 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); + userSession.post('/forms') + .send({form: myForm}) + .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); + // Delete an existing Form + userSession.delete('/forms/' + FormSaveRes.body._id) + .send(myForm) + .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); + // Set assertions + (FormDeleteRes.body._id).should.equal(FormSaveRes.body._id); - // // Call the assertion callback - // done(); - // }); - // }); + // 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; + myForm.admin = user; // Create new Form model instance - var FormObj = new Form(_Form); + var FormObj = new Form(myForm); // Save the Form FormObj.save(function() { @@ -297,7 +295,7 @@ describe('Form CRUD tests', function() { // Save a new Form userSession.post('/forms') - .send({form: _Form}) + .send({form: myForm}) .expect('Content-Type', /json/) .expect(200) .end(function(FormSaveErr, FormSaveRes) { @@ -333,8 +331,8 @@ describe('Form CRUD tests', function() { var FormObj, _Submission, submissionSession; beforeEach(function (done) { - _Form.admin = user; - FormObj = new Form(_Form); + myForm.admin = user; + FormObj = new Form(myForm); FormObj.save(function(err, form) { if (err) done(err); @@ -489,10 +487,9 @@ describe('Form CRUD tests', function() { }); }); - afterEach(function(done) { - User.remove().exec(function() { - Form.remove().exec(function() { + Form.remove({}).exec(function() { + User.remove({}).exec(function() { userSession.destroy(); done(); }); diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index 61d370ba..00fee0bc 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -85,7 +85,7 @@ describe('FormSubmission Model Unit Tests:', function() { } myForm = new Form({ title: 'Form Title1', - admin: user, + admin: user._id, language: 'english', form_fields: [ {'fieldType':'textfield', 'title':'What\'s your first name', 'fieldValue': ''}, @@ -117,8 +117,8 @@ describe('FormSubmission Model Unit Tests:', function() { } mySubmission = new FormSubmission({ - admin: user, - form: myForm, + admin: user._id, + form: myForm._id, timeElapsed: 17.55, form_fields: submissionFields }); @@ -137,7 +137,7 @@ describe('FormSubmission Model Unit Tests:', function() { myFieldMap[myForm.form_fields[0]._id+''] = 'firstName'; myFieldMap[myForm.form_fields[1]._id+''] = 'lastName'; myFieldMap[myForm.form_fields[2]._id+''] = 'sex'; - myFieldMap[myForm.form_fields[3]._id+''] = 'unparsedDOB'; + myFieldMap[myForm.form_fields[3]._id+''] = 'DOB'; myFieldMap[myForm.form_fields[4]._id+''] = 'phone'; myForm.plugins.oscarhost.settings.fieldMap = myFieldMap; @@ -213,7 +213,7 @@ describe('FormSubmission Model Unit Tests:', function() { }); }); it('should be able to findOne FormSubmission without problems', function(done) { - return FormSubmission.findOne({_id: mySubmission._id}, function(err,submission) { + return FormSubmission.findOne({_id: mySubmission._id}).exec(function(err,submission) { should.not.exist(err); should.exist(submission); should.deepEqual(submission.toObject(), mySubmission.toObject()); @@ -308,6 +308,6 @@ describe('FormSubmission Model Unit Tests:', function() { User.remove().exec(function() { FormSubmission.remove().exec(done); }); - }); + }) }); }); diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 2728090c..890c2748 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -42,123 +42,130 @@ describe('User CRUD tests', function() { }; // Create a new user - _User = { + // _User = { + // firstName: 'Full', + // lastName: 'Name', + // email: credentials.username, + // username: credentials.username, + // password: credentials.password, + // }; + }); + + // describe('Create, Verify and Activate a User', function() { + // var username = 'testActiveAccount1.be1e58fb@mailosaur.in'; + // var link, _tmpUser, activateToken; + // this.timeout(15000); + + // it('should be able to create a temporary (non-activated) User', function(done) { + // _User.email = _User.username = username; + // userSession.post('/auth/signup') + // .send(_User) + // .expect(200, 'An email has been sent to you. Please check it to verify your account.') + // .end(function(FormSaveErr, FormSaveRes) { + + // 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); + // activateToken = user.GENERATED_VERIFYING_URL; + + // done(); + // }); + + // // // mandrill('/messages/search', { + // // // query: "subject:Confirm", + // // // senders: [ + // // // "test@forms.polydaic.com" + // // // ], + // // // limit: 1 + // // // }, function(error, emails) { + // // // if (error) console.log( JSON.stringify(error) ); + + // // // var confirmation_email = emails[0]; + + // // // mandrill('/messages/content', { + // // // id: confirmation_email._id + // // // }, function(error, email) { + // // // if (error) console.log( JSON.stringify(error) ); + + // // // // console.log(email); + // // // var link = _(email.text.split('\n')).reverse().value()[1]; + // // // console.log(link); + // // // activateToken = _(url.parse(link).hash.split('/')).reverse().value()[0]; + // // // console.log('actual activateToken: '+ activateToken); + // // // console.log('expected activateToken: ' + user.GENERATED_VERIFYING_URL); + + // // // done(); + + // // // }); + // // // }); + + // // // mailbox.getEmails(function(err, _emails) { + // // // if(err) done(err); + + // // // var emails = _emails; + + // // // console.log('mailbox.getEmails:'); + // // // console.log(emails[0].text.links); + + // // // var link = emails[0].text.links[0].href; + // // // activateToken = _(url.parse(link).hash.split('/')).reverse().value()[0]; + // // // console.log('actual activateToken: '+ activateToken); + // // // console.log('expected activateToken: ' + user.GENERATED_VERIFYING_URL); + // // // (activateToken).should.equal(user.GENERATED_VERIFYING_URL); + + // // // done(); + // // // }); + // // }); + // }); + // }); + + // it('should be able to verify a User Account', function(done) { + // console.log('activateToken: '+activateToken); + // userSession.get('/auth/verify/'+activateToken) + // .expect(200) + // .end(function(VerifyErr, VerifyRes) { + // should.not.exist(VerifyErr); + // if(VerifyErr) console.log(VerifyRes.text); + // (VerifyRes.text).should.equal('User successfully verified'); + // done(); + // }); + // }); + + // // it('should receive confirmation email after verifying a User Account', function(done) { + // // mailbox.getEmails(function(err, _emails) { + // // if(err) throw err; + // // var email = _emails[0]; + + // // // console.log('mailbox.getEmails:'); + // // console.log(email); + // // (email.subject).should.equal('Account successfully verified!'); + // // done(); + // // }); + // // }); + // }); + + it('should be able to login and logout a User', function (done) { + var username = 'testActiveAccount.be1e58fb@mailosaur.in'; + // _User.email = _User.username = credentials.username = username; + // Create a new user + var newUser = { firstName: 'Full', lastName: 'Name', email: credentials.username, username: credentials.username, password: credentials.password, }; - }); - - describe('Create, Verify and Activate a User', function() { - var username = 'testActiveAccount1.be1e58fb@mailosaur.in'; - var link, _tmpUser, activateToken; - this.timeout(15000); - - it('should be able to create a temporary (non-activated) User', function(done) { - _User.email = _User.username = username; - userSession.post('/auth/signup') - .send(_User) - .expect(200, 'An email has been sent to you. Please check it to verify your account.') - .end(function(FormSaveErr, FormSaveRes) { - - 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); - activateToken = user.GENERATED_VERIFYING_URL; - - done(); - }); - - // // mandrill('/messages/search', { - // // query: "subject:Confirm", - // // senders: [ - // // "test@forms.polydaic.com" - // // ], - // // limit: 1 - // // }, function(error, emails) { - // // if (error) console.log( JSON.stringify(error) ); - - // // var confirmation_email = emails[0]; - - // // mandrill('/messages/content', { - // // id: confirmation_email._id - // // }, function(error, email) { - // // if (error) console.log( JSON.stringify(error) ); - - // // // console.log(email); - // // var link = _(email.text.split('\n')).reverse().value()[1]; - // // console.log(link); - // // activateToken = _(url.parse(link).hash.split('/')).reverse().value()[0]; - // // console.log('actual activateToken: '+ activateToken); - // // console.log('expected activateToken: ' + user.GENERATED_VERIFYING_URL); - - // // done(); - - // // }); - // // }); - - // // mailbox.getEmails(function(err, _emails) { - // // if(err) done(err); - - // // var emails = _emails; - - // // console.log('mailbox.getEmails:'); - // // console.log(emails[0].text.links); - - // // var link = emails[0].text.links[0].href; - // // activateToken = _(url.parse(link).hash.split('/')).reverse().value()[0]; - // // console.log('actual activateToken: '+ activateToken); - // // console.log('expected activateToken: ' + user.GENERATED_VERIFYING_URL); - // // (activateToken).should.equal(user.GENERATED_VERIFYING_URL); - - // // done(); - // // }); - // }); - }); - }); - - it('should be able to verify a User Account', function(done) { - console.log('activateToken: '+activateToken); - userSession.get('/auth/verify/'+activateToken) - .expect(200) - .end(function(VerifyErr, VerifyRes) { - should.not.exist(VerifyErr); - if(VerifyErr) console.log(VerifyRes.text); - (VerifyRes.text).should.equal('User successfully verified'); - done(); - }); - }); - - // it('should receive confirmation email after verifying a User Account', function(done) { - // mailbox.getEmails(function(err, _emails) { - // if(err) throw err; - // var email = _emails[0]; - - // // console.log('mailbox.getEmails:'); - // console.log(email); - // (email.subject).should.equal('Account successfully verified!'); - // done(); - // }); - // }); - }); - - it('should be able to login and logout a User', function (done) { - var username = 'testActiveAccount.be1e58fb@mailosaur.in'; - _User.email = _User.username = credentials.username = username; userSession.post('/auth/signup') - .send(_User) + .send(newUser) .expect(200) .end(function(FormSaveErr, FormSaveRes) { (FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.'); - userSession.post('/auth/signin') .send(credentials) .expect('Content-Type', /json/) @@ -183,9 +190,9 @@ describe('User CRUD tests', function() { }); }); - // it('should be able to reset a User\'s password'); + it('should be able to reset a User\'s password'); - // it('should be able to delete a User account without any problems'); + it('should be able to delete a User account without any problems'); afterEach(function(done) { User.remove().exec(function () { diff --git a/config/env/local.js b/config/env/local.js new file mode 100644 index 00000000..48b2534a --- /dev/null +++ b/config/env/local.js @@ -0,0 +1,17 @@ +'use strict'; + +var mandrill_api_key = 'AVCCf1C2dFlrNhx9Iyi_yQ'; + +//Use mandrill mock API_key if we are testing +// if(process.env.NODE_ENV === 'test') mandrill_api_key = '_YNOKLgT9DGb2sgVGR66yQ'; + +module.exports = { + // db: { + // uri: 'mongodb://localhost/local-dev', + // options: { + // user: '', + // pass: '' + // } + // }, + sessionSecret: process.env.SESSION_SECRET || 'somethingheresecret', +}; \ No newline at end of file diff --git a/gruntfile.js b/gruntfile.js index 29bfa499..064aef32 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -182,6 +182,8 @@ module.exports = function(grunt) { grunt.config.set('applicationJavaScriptFiles', config.assets.js); grunt.config.set('applicationCSSFiles', config.assets.css); }); + grunt.loadNpmTasks('grunt-html2js'); + // Default task(s). grunt.registerTask('default', ['lint', 'concurrent:default']); diff --git a/package.json b/package.json index 744e0624..0d6d31e9 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/whitef0x0/NodeForms.git" }, "engines": { - "node": "~0.10.28", + "node": "~0.12.6", "npm": "~1.4.28" }, "scripts": { @@ -22,6 +22,7 @@ }, "dependencies": { "async": "^1.4.2", + "bcrypt": "^0.8.5", "body-parser": "~1.9.0", "bower": "~1.3.8", "chalk": "~1.0.0", @@ -59,7 +60,7 @@ "karma-jasmine": "^0.2.3", "karma-phantomjs-launcher": "~0.1.2", "load-grunt-tasks": "~1.0.0", - "lodash": "~2.4.1", + "lodash": "^3.10.1", "mailosaur": "^1.0.1", "main-bower-files": "~2.8.2", "math": "0.0.3", @@ -92,6 +93,7 @@ "then-fs": "~2.0.0" }, "devDependencies": { + "grunt-html2js": "^0.3.5", "karma-chrome-launcher": "^0.1.12", "karma-jasmine-html-reporter": "^0.1.8", "karma-mocha-reporter": "^1.1.1", diff --git a/public/application.js b/public/application.js index 6529cf05..f3b09aaa 100755 --- a/public/application.js +++ b/public/application.js @@ -62,12 +62,15 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope' Auth.ensureHasCurrentUser(User); user = Auth.currentUser; + console.log(user.roles); + if(user){ authenticator = new Authorizer(user); + console.log('access denied: '+!authenticator.canAccess(permissions)); if( (permissions !== null) && !authenticator.canAccess(permissions) ){ event.preventDefault(); - console.log('access denied') + console.log('access denied'); $state.go('access_denied'); } } diff --git a/public/dist/application.js b/public/dist/application.js index 52b8e64e..fd150dad 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -47,55 +47,55 @@ angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_RO superuser: 'superuser', }); -// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', -// function($rootScope, Auth, $state, $stateParams) { +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', + function($rootScope, Auth, $state, $stateParams) { -// $rootScope.$state = $state; -// $rootScope.$stateParams = $stateParams; + $rootScope.$state = $state; + $rootScope.$stateParams = $stateParams; -// // add previous state property -// $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { -// $state.previous = fromState; + // add previous state property + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { + $state.previous = fromState; -// //Redirect to listForms if user is authenticated -// if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){ -// if(Auth.isAuthenticated()){ -// event.preventDefault(); // stop current execution -// $state.go('listForms'); // go to listForms page -// } -// } -// //Redirect to 'home' route if user is not authenticated -// else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){ -// event.preventDefault(); // stop current execution -// $state.go('home'); // go to listForms page -// } + //Redirect to listForms if user is authenticated + if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){ + if(Auth.isAuthenticated()){ + event.preventDefault(); // stop current execution + $state.go('listForms'); // go to listForms page + } + } + //Redirect to 'home' route if user is not authenticated + else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){ + event.preventDefault(); // stop current execution + $state.go('home'); // go to listForms page + } -// }); + }); -// } -// ]); + } +]); -// //Page access/authorization logic -// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams', -// function($rootScope, Auth, User, Authorizer, $state, $stateParams) { -// $rootScope.$on('$stateChangeStart', function(event, next) { -// var authenticator, permissions, user; -// permissions = next && next.data && next.data.permissions ? next.data.permissions : null; +//Page access/authorization logic +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams', + function($rootScope, Auth, User, Authorizer, $state, $stateParams) { + $rootScope.$on('$stateChangeStart', function(event, next) { + var authenticator, permissions, user; + permissions = next && next.data && next.data.permissions ? next.data.permissions : null; -// Auth.ensureHasCurrentUser(User); -// user = Auth.currentUser; + Auth.ensureHasCurrentUser(User); + user = Auth.currentUser; -// if(user){ -// authenticator = new Authorizer(user); + if(user){ + authenticator = new Authorizer(user); -// if( (permissions !== null) && !authenticator.canAccess(permissions) ){ -// event.preventDefault(); -// console.log('access denied') -// $state.go('access_denied'); -// } -// } -// }); -// }]); + if( (permissions !== null) && !authenticator.canAccess(permissions) ){ + event.preventDefault(); + console.log('access denied') + $state.go('access_denied'); + } + } + }); +}]); //Then define the init function for starting up the application angular.element(document).ready(function() { @@ -420,20 +420,21 @@ angular.module('forms').config(['$stateProvider', permissions: [ 'editForm' ] } }). + state('submitForm', { + url: '/forms/:formId', + templateUrl: 'modules/forms/views/submit-form.client.view.html', + data: { + hideNav: true, + }, + }). state('viewForm', { url: '/forms/:formId/admin', templateUrl: 'modules/forms/views/admin-form.client.view.html', data: { permissions: [ 'editForm' ] } - }). - state('viewPublicForm', { - url: '/forms/:formId', - templateUrl: 'modules/forms/views/view-public-form.client.view.html', - data: { - hideNav: true, - }, - }); + }); + } ]); 'use strict'; @@ -445,15 +446,23 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope $scope = $rootScope; $scope.myform = CurrentForm.getForm(); + $scope.myform._id = $stateParams.formId; $rootScope.saveInProgress = false; // Find a specific Form $scope.findOne = function(){ - $scope.myform = Forms.get({ + Forms.get({ formId: $stateParams.formId + }, function(form){ + CurrentForm.setForm(form); + $scope.myform = form; + $scope.myform._id = $stateParams.formId; + }, function(err){ + console.error('Could not fetch form'); + console.error(err); }); - CurrentForm.setForm($scope.myform); }; + $scope.setForm = function(form){ $scope.myform = form; }; @@ -676,6 +685,8 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun require: ['^form'], restrict: 'AE', link: function($scope, $element, $attrs, $ctrls) { + + //DAVID: TODO: Do we really need to check if our directive element is ready everytime angular.element(document).ready(function() { var $formCtrl = $ctrls[0], @@ -702,7 +713,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun return false; }; - var debounceSave = function () { + this.debounceSave = function () { $rootScope.saveInProgress = true; $rootScope[$attrs.autoSaveCallback](true, function(err){ @@ -719,7 +730,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun //Update/save Form if any Form fields are Dirty and Touched $scope.$watch(function(newValue, oldValue) { if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){ - debounceSave(); + this.debounceSave(); } }); @@ -749,7 +760,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun savePromise = $timeout(function() { console.log('Saving Form'); - debounceSave(); + this.debounceSave(); }); } //If we are finished rendering then form saving should be finished @@ -1092,35 +1103,6 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', rows: [] }; - //Fetch and display submissions of Form - $scope.initFormSubmissions = function(){ - $http.get('/forms/'+$scope.myform._id+'/submissions') - .success(function(data, status, headers){ - - console.log(data[0].form_fields); - - var _tmpSubFormFields, - defaultFormFields = _.cloneDeep($scope.myform.form_fields); - - - //Iterate through form's submissions - for(var i=0; i= 0) { +// templateUrl += type + '.html'; +// } +// var template = $templateCache.get(templateUrl); +// return template; +// }; +// return { +// restrict: 'E', +// template: '
Start Page
', +// scope: { +// 'pageData': '=', +// 'pageType': '&' +// }, +// link: function(scope, element) { + +// // console.log(attrs); +// console.log('scope.pageData'); +// // console.log(scope); +// scope.exitStartPage = function() { +// // console.log(scope.pageData); +// // if(attrs.pageData.showStart) attrs.pageData.showStart = false; +// }; + +// var template = getTemplateUrl(scope.pageType); +// element.html(template); +// $compile(element.contents())(scope); +// }, +// controller: function($scope){ +// console.log('entryPage Controller'); +// console.log($scope.pageData); +// // $scope.exitStartPage = function() { +// // if($scope.pageData.showStart) scope.pageData.showStart = false; +// // }; +// } +// }; +// }]); 'use strict'; angular.module('forms').directive('fieldIconDirective', function($http, $compile) { @@ -1294,8 +1352,9 @@ angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', // GET template content from path var template = getTemplateUrl(scope.field); // $http.get(templateUrl).success(function(data) { - element.html(template); - $compile(element.contents())(scope); + element.html(template).show(); + // console.log(element.contents()); + $compile(element.contents())(scope); // }); }; @@ -1346,46 +1405,49 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo 'use strict'; -angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope', +angular.module('forms').directive('submitFormDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope', function ($http, $timeout, TimeCounter, Auth, $filter, $rootScope) { return { templateUrl: 'modules/forms/views/directiveViews/form/submit-form.client.view.html', restrict: 'E', scope: { - form:'=' + myform:'=' }, controller: function($scope){ angular.element(document).ready(function() { - + $scope.error = ''; $scope.selected = null; + $scope.submitted = false; + TimeCounter.startClock() + $scope.exitStartPage = function(){ + $scope.myform.startPage.showStart = false; + } $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; - // console.log('percentageComplete: '+$filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100+'%'); - $scope.form.percentageComplete = $filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100; - console.log($scope.form.percentageComplete); - // delete $scope.form.visible_form_fields; + var form = _.cloneDeep($scope.myform); + form.timeElapsed = _timeElapsed; + + // console.log('percentageComplete: '+$filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100+'%'); + form.percentageComplete = $filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100; + console.log(form.percentageComplete) + delete form.visible_form_fields; $scope.authentication = Auth; - $scope.submitPromise = $http.post('/forms/'+$scope.form._id,$scope.form) + $scope.submitPromise = $http.post('/forms/'+$scope.myform._id, form) .success(function(data, status, headers){ console.log('form submitted successfully'); - // alert('Form submitted..'); - $scope.form.submitted = true; + $scope.myform.submitted = true; }) .error(function(error){ console.log(error); @@ -1393,19 +1455,17 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCo }); }; - - $scope.exitstartPage = function () { - $scope.form.startPage.showStart = false; - }; - $scope.reloadForm = function(){ + //Reset Timer TimeCounter.stopClock(); TimeCounter.startClock(); - $scope.form.submitted = false; - $scope.form.form_fields = _.chain($scope.form.form_fields).map(function(field){ - field.fieldValue = ''; - return field; - }).value(); + + //Reset Form + $scope.myform.submitted = false; + $scope.myform.form_fields = _.chain($scope.myform.form_fields).map(function(field){ + field.fieldValue = ''; + return field; + }).value(); }; }); @@ -1730,12 +1790,11 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca $scope = $rootScope; $scope.credentials = {}; - $scope.error = null; + $scope.error = ''; $scope.signin = function() { User.login($scope.credentials).then( function(response) { - // console.log(response); Auth.login(response); $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); @@ -1757,18 +1816,21 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca $scope.signup = function() { User.signup($scope.credentials).then( - function(response) { - console.log('signup-success'); - $state.go('signup-success'); - }, - function(error) { - if(error) { - $scope.error = error; - }else { - console.log('No response received'); - } - } - ); + function(response) { + console.log('signup-success'); + $state.go('signup-success'); + }, + function(error) { + console.log('Error: '); + console.log(error); + if(error) { + $scope.error = error; + console.log(error); + }else { + console.log('No response received'); + } + } + ); }; } @@ -1777,10 +1839,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User', function($scope, $stateParams, $state, User) { - - //If user is signed in then redirect back home - // if ($scope.authentication.isAuthenticated()) $state.go('home'); - + // Submit forgotten password account id $scope.askForPasswordReset = function() { User.askForPasswordReset($scope.credentials).then( @@ -1819,73 +1878,68 @@ angular.module('users').controller('PasswordController', ['$scope', '$stateParam angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users', function($scope, $rootScope, $http, $state, Users) { - $scope.user = $rootScope.user; - console.log($scope.user); - // If user is not signed in then redirect back home - if (!$scope.user) $state.go('home'); + $scope.user = $rootScope.user; - // Check if there are additional accounts - $scope.hasConnectedAdditionalSocialAccounts = function(provider) { - for (var i in $scope.user.additionalProvidersData) { - return true; + // Check if there are additional accounts + $scope.hasConnectedAdditionalSocialAccounts = function(provider) { + for (var i in $scope.user.additionalProvidersData) { + return true; + } + return false; + }; + + // Check if provider is already in use with current user + $scope.isConnectedSocialAccount = function(provider) { + return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]); + }; + + // Remove a user social account + $scope.removeUserSocialAccount = function(provider) { + $scope.success = $scope.error = null; + + $http.delete('/users/accounts', { + params: { + provider: provider } + }).success(function(response) { + // If successful show success message and clear form + $scope.success = true; + $scope.user = response; + }).error(function(response) { + $scope.error = response.message; + }); + }; - return false; - }; - - // Check if provider is already in use with current user - $scope.isConnectedSocialAccount = function(provider) { - return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]); - }; - - // Remove a user social account - $scope.removeUserSocialAccount = function(provider) { + // Update a user profile + $scope.updateUserProfile = function(isValid) { + if (isValid) { $scope.success = $scope.error = null; + var user = new Users($scope.user); - $http.delete('/users/accounts', { - params: { - provider: provider - } - }).success(function(response) { - // If successful show success message and clear form + user.$update(function(response) { $scope.success = true; $scope.user = response; - }).error(function(response) { - $scope.error = response.message; + }, function(response) { + $scope.error = response.data.message; }); - }; + } else { + $scope.submitted = true; + } + }; - // Update a user profile - $scope.updateUserProfile = function(isValid) { - if (isValid) { - $scope.success = $scope.error = null; - var user = new Users($scope.user); + // Change user password + $scope.changeUserPassword = function() { + $scope.success = $scope.error = null; - user.$update(function(response) { - $scope.success = true; - $scope.user = response; - }, function(response) { - $scope.error = response.data.message; - }); - } else { - $scope.submitted = true; - } - }; + $http.post('/users/password', $scope.passwordDetails).success(function(response) { + // If successful show success message and clear form + $scope.success = true; + $scope.passwordDetails = null; + }).error(function(response) { + $scope.error = response.message; + }); + }; - // Change user password - $scope.changeUserPassword = function() { - $scope.success = $scope.error = null; - - $http.post('/users/password', $scope.passwordDetails).success(function(response) { - // If successful show success message and clear form - $scope.success = true; - $scope.passwordDetails = null; - }).error(function(response) { - $scope.error = response.message; - }); - }; - - // }); } ]); 'use strict'; @@ -1938,41 +1992,46 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro ]); 'use strict'; -angular.module('users').factory('Auth', function($window) { +angular.module('users').factory('Auth', ['$window', + function($window) { + var userState = { isLoggedIn: false }; var service = { - currentUser: null, + _currentUser: null, + get currentUser(){ + return this._currentUser; + }, // Note: we can't make the User a dependency of Auth // because that would create a circular dependency // Auth <- $http <- $resource <- LoopBackResource <- User <- Auth ensureHasCurrentUser: function(User) { - if (service.currentUser && service.currentUser.username) { + if (service._currentUser && service._currentUser.username) { console.log('Using local current user.'); - // console.log(service.currentUser); - return service.currentUser; + // console.log(service._currentUser); + return service._currentUser; } else if ($window.user){ console.log('Using cached current user.'); // console.log($window.user); - service.currentUser = $window.user; - return service.currentUser; + service._currentUser = $window.user; + return service._currentUser; } else{ console.log('Fetching current user from the server.'); User.getCurrent().then(function(user) { // success - service.currentUser = user; + service._currentUser = user; userState.isLoggedIn = true; - $window.user = service.currentUser; - return service.currentUser; + $window.user = service._currentUser; + return service._currentUser; }, function(response) { userState.isLoggedIn = false; - service.currentUser = null; + service._currentUser = null; $window.user = null; console.log('User.getCurrent() err', response); return null; @@ -1981,7 +2040,7 @@ angular.module('users').factory('Auth', function($window) { }, isAuthenticated: function() { - return !!service.currentUser; + return !!service._currentUser; }, getUserState: function() { @@ -1990,17 +2049,19 @@ angular.module('users').factory('Auth', function($window) { login: function(new_user) { userState.isLoggedIn = true; - service.currentUser = new_user; + service._currentUser = new_user; }, logout: function() { $window.user = null; userState.isLoggedIn = false; - service.currentUser = null; + service._currentUser = null; }, }; return service; - }); + + } +]); 'use strict'; @@ -2041,7 +2102,6 @@ angular.module('users').service('Authorizer', function(APP_PERMISSIONS, USER_ROL angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '$state', function($window, $q, $timeout, $http, $state) { - var userService = { getCurrent: function() { var deferred = $q.defer(); @@ -2064,9 +2124,11 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' }).error(function(error) { deferred.reject(error.message || error); }); - return deferred.promise; + + return deferred.promise; }, logout: function() { + var deferred = $q.defer(); $http.get('/auth/signout').success(function(response) { deferred.resolve(null); @@ -2079,12 +2141,10 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' signup: function(credentials) { var deferred = $q.defer(); - $http.post('/auth/signup', credentials).success(function(response) { // If successful we assign the response to the global user model deferred.resolve(response); }).error(function(error) { - deferred.reject(error.message || error); }); @@ -2092,8 +2152,9 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' }, resendVerifyEmail: function(_email) { + var deferred = $q.defer(); - $http.post('/auth/verify/', {email: _email}).success(function(response) { + $http.post('/auth/verify', {email: _email}).success(function(response) { deferred.resolve(response); }).error(function(error) { deferred.reject(error.message || error); @@ -2103,6 +2164,12 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' }, validateVerifyToken: function(token) { + + //DAVID: TODO: The valid length of a token should somehow be linked to server config values + //DAVID: TODO: SEMI-URGENT: Should we even be doing this? + var validTokenRe = /^([A-Za-z0-9]{48})$/g; + if( !validTokenRe.test(token) ) throw new Error('Error token: '+token+' is not a valid verification token'); + var deferred = $q.defer(); $http.get('/auth/verify/'+token).success(function(response) { deferred.resolve(response); @@ -2113,7 +2180,8 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' return deferred.promise; }, - resetPassword: function(passwordDetails, token) { + resetPassword: function(passwordDetails, token) { + var deferred = $q.defer(); $http.get('/auth/password/'+token, passwordDetails).success(function(response) { deferred.resolve(); @@ -2126,12 +2194,11 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' // Submit forgotten password account id askForPasswordReset: function(credentials) { + var deferred = $q.defer(); $http.post('/auth/forgot', credentials).success(function(response) { // Show user success message and clear form - deferred.resolve(response); - }).error(function(error) { // Show user error message deferred.reject(error.message || error); diff --git a/public/dist/application.min.css b/public/dist/application.min.css index 3f304ef3..68153c48 100644 --- a/public/dist/application.min.css +++ b/public/dist/application.min.css @@ -1 +1 @@ -.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.content{margin-top:70px}.undecorated-link:hover{text-decoration:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{position:fixed;top:0;left:0;height:100%;width:100%;z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff;background-color:rgba(250,120,126,.65) #FA787E}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select option{font-weight:400}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}section.content p.breakwords{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px;font-weight:400}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.admin-form .panel-heading a:hover{text-decoration:none}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.current-fields .tool-panel>.panel-default .panel-heading a:hover{text-decoration:none}.submissions-table .table-outer.row{margin:1.5em 0 2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 6em 7em}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;background-color:#fff;border-radius:7px;width:100%;border:25px solid #fff}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file +body{overflow-x:hidden}.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.content{margin-top:70px}.undecorated-link:hover{text-decoration:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{position:fixed;top:0;left:0;height:100%;width:100%;z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff;background-color:rgba(250,120,126,.65) #FA787E}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select option{font-weight:400}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}section.content p.breakwords{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px;font-weight:400}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.admin-form .panel-heading a:hover{text-decoration:none}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.current-fields .tool-panel>.panel-default .panel-heading a:hover{text-decoration:none}.submissions-table .table-outer.row{margin:1.5em 0 2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 6em 7em}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;background-color:#fff;border-radius:7px;width:100%;border:25px solid #fff}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file diff --git a/public/dist/application.min.js b/public/dist/application.min.js index c3ce94c8..066c3901 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,2 +1,2 @@ -"use strict";var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]}}).state("viewPublicForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/view-public-form.client.view.html",data:{hideNav:!0}})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$modal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController"})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){err=response.data})["finally"](function(){updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb&&cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicate=function(form_index){var form=_.clone($scope.myforms[form_index]);form._id="",$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form duplicated"),$scope.myforms.splice(form_index+1,0,data),console.log($scope.myforms[3]._id)}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.createNew=function(){console.log($scope.forms.createForm);var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm","Auth",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm,Auth){$scope.authentication=Auth,$scope.initForm=function(){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.myform=form,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))},function(error){throw $scope.error=error.message,console.log("ERROR: "+error.message),new Error("Error: "+error.message)})}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",controller:function($scope){},link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("changeFocus",function(){return{scope:{focusDownId:"@",focusUpId:"@"},link:function(scope,elem,attrs){scope.focusUp=function(){scope.$first||(console.log("focusUp"),elem[0].previousElementSibling.find("input").focus()),scope.apply()},scope.focusDown=function(){scope.$last||elem[0].nextElementSibling.focus(),scope.apply()},angular.element("#"+scope.focusDownId).bind("click",function(){scope.focusDown()}),angular.element("#"+scope.focusUpId).bind("click",function(){scope.focusUp()})}}}),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:function($scope){$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages;var _current_upload=null;$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update;$scope.pdfFields;$scope.cancelUpload=function(){_current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(files){if(files&&files.length){var file=files[0];console.log(file),_current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),console.log($scope.myform.pdf),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","timeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:function($scope){$scope.addField={},$scope.addField.types=FormFields.fields,$scope.addField.types.forEach(function(type){return type.lastAddedID=1,type}),$scope.accordion={},$scope.accordion.oneAtATime=!0,$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},$scope.addNewField=function(addOrReturn,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1};return console.log("\n\n---------\nAdded field CLIENT"),console.log(newField),addOrReturn?void $scope.myform.form_fields.push(newField):newField},$scope.deleteField=function(hashKey){for(var i=0;i<$scope.myform.form_fields.length;i++)if($scope.myform.form_fields[i].$$hashKey===hashKey){$scope.myform.form_fields.splice(i,1);break}},$scope.duplicateField=function(field_index){console.log("field_index: "+field_index);var field=$scope.addNewField(!1,$scope.myform.form_fields[field_index].fieldType);field.title=$scope.myform.form_fields[field_index].title,console.log($scope.myform.form_fields[field_index]),$scope.myform.form_fields.splice(field_index+1,0,field)},$scope.addButton=function(newButtons){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var hashKey=_.chain(button.$$hashKey).words().last().parseInt().value(),i=0;i<$scope.myform.startPage.buttons.length;i++){var currHashKey=_.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();if(currHashKey===hashKey){$scope.myform.startPage.buttons.splice(i,1);break}}},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="./modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0?templateUrl+=type+".html":void 0},linker=function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType?scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0}:"natural"===scope.field.fieldType&&(scope.field.fieldMatchValue="",scope.$watch("scope.field",function(newField,oldField){}));var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data),$compile(element.contents())(scope)})};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$last?scope.$last&&$timeout(function(){element.ready(function(){$rootScope.$broadcast(broadcastMessage+"Finished")})}):$timeout(function(){$rootScope.$broadcast(broadcastMessage+"Started")})}}}}),angular.module("forms").directive("submissionsFormDirective",["$rootScope","$http","Upload","$timeout","timeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,timeCounter,Auth,FormFields){return{templateUrl:"./modules/forms/views/directiveViews/form/submissions-form.client.view.html",restrict:"E",scope:{myform:"=",user:"="},controller:function($scope){$scope.table={masterChecker:!1,rows:[]},$scope.isAtLeastOneChecked=function(){for(var i=0;i<$scope.table.rows.length;i++)if($scope.table.rows[i].selected)return!0;return!1},$scope.toggleAllCheckers=function(){for(var i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected=$scope.table.masterChecker},$scope.toggleObjSelection=function($event,description){$event.stopPropagation()},$scope.rowClicked=function(row_index){$scope.table.rows[row_index].selected=!$scope.table.rows[row_index].selected},$scope.deleteSelectedSubmissions=function(){var delete_ids=_.chain($scope.table.rows).filter(function(row){return!!row.selected}).pluck("_id").value();$http({url:"/forms/"+$scope.myform._id+"/submissions",method:"DELETE",data:{deleted_submissions:delete_ids},headers:{"Content-Type":"application/json;charset=utf-8"}}).success(function(data,status,headers){for(var tmpArray=[],i=0;i<$scope.table.rows.length;i++)$scope.table.rows[i].selected||tmpArray.push($scope.table.rows[i]);console.log(tmpArray),$scope.table.rows=tmpArray}).error(function(err){console.log("Could not delete form submissions.\nError: "),console.log(err),console.error=err})},$scope.exportSubmissions=function(type){var fileMIMETypeMap={xls:"vnd.openxmlformats-officedocument.spreadsheetml.sheet",json:"json",csv:"csv"},blob=new Blob([document.getElementById("table-submission-data").innerHTM],{type:"application/"+fileMIMETypeMap[type]+";charset=utf-8"});saveAs(blob,$scope.myform.title+"_sumbissions_export_"+Date.now()+"."+type)},$scope.showSubmissions=function(){$http.get("/forms/"+$scope.myform._id+"/submissions").success(function(data,status,headers){for(var _tmpSubFormFields,_data=[],defaultFormFields=JSON.parse(JSON.stringify($scope.myform.form_fields)),i=0;ii;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +"use strict";var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","Auth","$state",function($rootScope,$scope,User,Auth,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate})}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html",data:{permissions:["editForm"]}}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]}}).state("viewPublicForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/view-public-form.client.view.html",data:{hideNav:!0}})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$modal",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$modal){$scope=$rootScope,$scope.myform=CurrentForm.getForm(),$rootScope.saveInProgress=!1,$scope.findOne=function(){$scope.myform=Forms.get({formId:$stateParams.formId}),CurrentForm.setForm($scope.myform)},$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$modal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController"})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){err=response.data})["finally"](function(){updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb&&cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicate=function(form_index){var form=_.clone($scope.myforms[form_index]);form._id="",$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("form duplicated"),$scope.myforms.splice(form_index+1,0,data),console.log($scope.myforms[3]._id)}).error(function(errorResponse){console.log(errorResponse),$scope.error=errorResponse.data.message})},$scope.createNew=function(){console.log($scope.forms.createForm);var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$stateParams","$state","Forms","CurrentForm","Auth",function($scope,$rootScope,$stateParams,$state,Forms,CurrentForm,Auth){$scope.authentication=Auth,$scope.initForm=function(){Forms.get({formId:$stateParams.formId}).$promise.then(function(form){$scope.myform=form,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))},function(error){$scope.error=error.message,console.error("ERROR: "+error.message),$state.go("access_denied")})}}]),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFieldsStarted",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFieldsFinished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine())})};$scope.$watch(function(newValue,oldValue){$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){var changedFields=!_.isEqual(oldValue,newValue);(newValue||oldValue)&&oldValue&&($rootScope.finishedRender&&changedFields&&!$formCtrl.$dirty&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){console.log("Saving Form"),debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","$timeout","TimeCounter","Auth","FormFields",function($rootScope,$http,Upload,$timeout,TimeCounter,Auth,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:function($scope){$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._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(console.log(files),files&&files.length){var file=files[0];console.log(file),this._current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),console.log($scope.myform.pdf),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}}}]),angular.module("forms").directive("editFormDirective",["$rootScope","$q","$http","$timeout","TimeCounter","Auth","FormFields",function($rootScope,$q,$http,$timeout,TimeCounter,Auth,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:function($scope){$scope.addField={},$scope.addField.types=FormFields.types,$scope.addField.types.forEach(function(type){return type.lastAddedID=1,type}),$scope.lastButtonID=0,$scope.accordion={},$scope.accordion.oneAtATime=!0,$scope.update=$rootScope.update,$scope.dropzone={handle:" .handle"},$scope.addNewField=function(modifyForm,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,deletePreserved:!1};return newField._id=_.uniqueId(),modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=$scope.myform.form_fields[field_index];$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=_.uniqueId(),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_title:"Option "+option_id,option_value:option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$templateCache","$http","$compile","$rootScope",function($templateCache,$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"];__indexOf.call(supported_fields,type)>=0&&(templateUrl+=type+".html");var template=$templateCache.get(templateUrl);return template},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});var template=getTemplateUrl(scope.field);element.html(template),$compile(element.contents())(scope)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&"},link:linker}}]),angular.module("forms").directive("onFinishRender",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}),angular.module("forms").directive("formDirective",["$http","$timeout","TimeCounter","Auth","$filter","$rootScope",function($http,$timeout,TimeCounter,Auth,$filter,$rootScope){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{form:"="},controller:function($scope){angular.element(document).ready(function(){$scope.selected=null,TimeCounter.startClock(),$rootScope.setActiveField=function(field_id){$scope.selected=field_id},$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").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"checkbox",value:"Checkbox"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.startClock=function(){_startTime=Date.now()},this.stopClock=function(){return _endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}})}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error=null,$scope.signin=function(){User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){error?$scope.error=error:console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,console.log($scope.user),$scope.user||$state.go("home"),$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isReset=!1,$scope.credentials={},$scope.resendVerifyEmail=function(){console.log($scope.credentials.email),User.resendVerifyEmail($scope.credentials.email).then(function(response){$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials=null,$scope.isReset=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isReset=!0,$scope.credentials=null},function(error){console.log("Error: "+error.message),$scope.isReset=!1,$scope.error=error,$scope.credentials=null}))}}]),angular.module("users").factory("Auth",function($window){var userState={isLoggedIn:!1},service={currentUser:null,ensureHasCurrentUser:function(User){return service.currentUser&&service.currentUser.username?(console.log("Using local current user."),service.currentUser):$window.user?(console.log("Using cached current user."),service.currentUser=$window.user,service.currentUser):(console.log("Fetching current user from the server."),void User.getCurrent().then(function(user){return service.currentUser=user,userState.isLoggedIn=!0, +$window.user=service.currentUser,service.currentUser},function(response){return userState.isLoggedIn=!1,service.currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null}))},isAuthenticated:function(){return!!service.currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service.currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service.currentUser=null}};return service}),angular.module("users").service("Authorizer",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify/",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/forms/config/forms.client.routes.js b/public/modules/forms/config/forms.client.routes.js index a04f4c41..f788bb3b 100644 --- a/public/modules/forms/config/forms.client.routes.js +++ b/public/modules/forms/config/forms.client.routes.js @@ -19,13 +19,27 @@ angular.module('forms').config(['$stateProvider', data: { hideNav: true, }, + resolve: { + Forms: 'Forms', + myForm: function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + }, + }, + controller: 'SubmitFormController' }). state('viewForm', { url: '/forms/:formId/admin', templateUrl: 'modules/forms/views/admin-form.client.view.html', data: { permissions: [ 'editForm' ] - } + }, + resolve: { + Forms: 'Forms', + myForm: function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + }, + }, + controller: 'AdminFormController' }); } diff --git a/public/modules/forms/controllers/admin-form.client.controller.js b/public/modules/forms/controllers/admin-form.client.controller.js index b3f85146..dfaf00f1 100644 --- a/public/modules/forms/controllers/admin-form.client.controller.js +++ b/public/modules/forms/controllers/admin-form.client.controller.js @@ -1,14 +1,16 @@ '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) { +angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$modal', 'myForm', + function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http, $modal, myForm) { $scope = $rootScope; - $scope.myform = CurrentForm.getForm(); - $scope.myform._id = $stateParams.formId; + $scope.myform = myForm; $rootScope.saveInProgress = false; + CurrentForm.setForm($scope.myform); + + // console.log($scope.myform); // Find a specific Form $scope.findOne = function(){ @@ -105,5 +107,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope } }; + } ]); \ No newline at end of file diff --git a/public/modules/forms/controllers/submit-form.client.controller.js b/public/modules/forms/controllers/submit-form.client.controller.js index 20ee9abc..4e72e24d 100644 --- a/public/modules/forms/controllers/submit-form.client.controller.js +++ b/public/modules/forms/controllers/submit-form.client.controller.js @@ -1,40 +1,24 @@ 'use strict'; // Forms controller -angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', 'Auth', - function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm, Auth) { +angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$stateParams', '$state', 'Forms', 'CurrentForm', 'Auth', 'myForm', + function($scope, $rootScope, $stateParams, $state, Forms, CurrentForm, Auth, myForm) { $scope.authentication = Auth; - - $scope.initForm = function(){ - Forms.get({ - formId: $stateParams.formId - }).$promise.then( - //success - function(form){ - $scope.myform = form; + $scope.myform = myForm; - if(!$scope.myform.isLive){ - // Show navbar if form is not public AND user IS loggedin - if($scope.authentication.isAuthenticated()){ - $scope.hideNav = $rootScope.hideNav = false; - } - // Redirect if form is not public user IS NOT loggedin - else { - $scope.hideNav = $rootScope.hideNav = true; - $state.go('access_denied'); - } - }else{ - $scope.hideNav = $rootScope.hideNav = true; - } - }, - //error - function( error ){ - $scope.error = error.message; - console.error('ERROR: '+error.message); - $state.go('access_denied'); - } - ); - }; + if(!$scope.myform.isLive){ + // Show navbar if form is not public AND user IS loggedin + if($scope.authentication.isAuthenticated()){ + $scope.hideNav = $rootScope.hideNav = false; + } + // Redirect if form is not public user IS NOT loggedin + else { + $scope.hideNav = $rootScope.hideNav = true; + $state.go('access_denied'); + } + }else{ + $scope.hideNav = $rootScope.hideNav = true; + } } ]); \ No newline at end of file diff --git a/public/modules/forms/css/form.css b/public/modules/forms/css/form.css index ef1d68b7..16b35ee5 100644 --- a/public/modules/forms/css/form.css +++ b/public/modules/forms/css/form.css @@ -290,6 +290,10 @@ div.config-form .row.field { border-radius: 4px; } + .admin-form .oscar-field-select { + margin: 10px 0 10px; + } + .view-form-btn.span { padding-right:0.6em; } diff --git a/public/modules/forms/directives/auto-save.client.directive.js b/public/modules/forms/directives/auto-save.client.directive.js index b24d107f..d73e14dd 100644 --- a/public/modules/forms/directives/auto-save.client.directive.js +++ b/public/modules/forms/directives/auto-save.client.directive.js @@ -1,5 +1,18 @@ 'use strict'; +_.mixin({ removeDateFields : function(o){ + var clone = _.clone(o); + for(var i=0; i FormFields + $scope.oscarFieldsLeft = function(field_id){ + + if($scope.myform && $scope.myform.plugins.oscarhost.settings.validFields.length > 0){ + if(!$scope.myform.plugins.oscarhost.settings.fieldMap) $scope.myform.plugins.oscarhost.settings.fieldMap = {}; + + var oscarhostFields = $scope.myform.plugins.oscarhost.settings.validFields; + var currentFields = _($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value(); + + if( $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id) ){ + currentFields = _(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id]); + } + + // console.log($scope.myform.plugins.oscarhost.settings.fieldMap); + //Get all oscarhostFields that haven't been mapped to a formfield + return _(oscarhostFields).difference(currentFields).value(); + } + return []; + }; + /* ** FormFields (ui-sortable) drag-and-drop configuration */ @@ -38,7 +61,6 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht handle: ' .handle' }; - // $scope.draggable = { // connectWith: ".dropzone", // start: function (e, ui) { @@ -111,7 +133,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht }; // console.log('\n\n---------\nAdded field CLIENT'); // console.log(newField); - newField._id = _.uniqueId(); + // newField._id = _.uniqueId(); // put newField into fields array if(modifyForm){ @@ -122,6 +144,12 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht // Delete particular field on button click $scope.deleteField = function (field_index){ + $scope.myform.plugins.oscarhost.settings.fieldMap = {}; + //Delete field from field map + var currFieldId = $scope.myform.form_fields[field_index]._id + delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId]; + + //Delete field $scope.myform.form_fields.splice(field_index, 1); }; $scope.duplicateField = function (field_index){ @@ -184,8 +212,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht var newOption = { 'option_id' : option_id, - 'option_title' : 'Option ' + option_id, - 'option_value' : option_id + 'option_value' : 'Option ' + option_id, }; // put new option into fieldOptions array diff --git a/public/modules/forms/directives/entry_page.client.directive.js b/public/modules/forms/directives/entry_page.client.directive.js deleted file mode 100644 index fbbf80ce..00000000 --- a/public/modules/forms/directives/entry_page.client.directive.js +++ /dev/null @@ -1,47 +0,0 @@ -// 'use strict'; - -// angular.module('forms').directive('entryPage', ['$templateCache', '$http', '$compile', '$rootScope', -// function($templateCache, $http, $compile, $rootScope) { -// var getTemplateUrl = function(type) { - -// var templateUrl = 'modules/forms/views/directiveViews/entryPage/'; -// var supported_pages = [ -// 'welcome', -// 'thankyou' -// ]; -// if (__indexOf.call(supported_pages, type) >= 0) { -// templateUrl += type + '.html'; -// } -// var template = $templateCache.get(templateUrl); -// return template; -// }; -// return { -// restrict: 'E', -// template: '
Start Page
', -// scope: { -// 'pageData': '=', -// 'pageType': '&' -// }, -// link: function(scope, element) { - -// // console.log(attrs); -// console.log('scope.pageData'); -// // console.log(scope); -// scope.exitStartPage = function() { -// // console.log(scope.pageData); -// // if(attrs.pageData.showStart) attrs.pageData.showStart = false; -// }; - -// var template = getTemplateUrl(scope.pageType); -// element.html(template); -// $compile(element.contents())(scope); -// }, -// controller: function($scope){ -// console.log('entryPage Controller'); -// console.log($scope.pageData); -// // $scope.exitStartPage = function() { -// // if($scope.pageData.showStart) scope.pageData.showStart = false; -// // }; -// } -// }; -// }]); \ No newline at end of file diff --git a/public/modules/forms/directives/field.client.directive.js b/public/modules/forms/directives/field.client.directive.js index d11d82ca..300879fe 100644 --- a/public/modules/forms/directives/field.client.directive.js +++ b/public/modules/forms/directives/field.client.directive.js @@ -13,7 +13,7 @@ angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', var getTemplateUrl = function(field) { - + console.log(field.validFieldTypes); var type = field.fieldType; var templateUrl = 'modules/forms/views/directiveViews/field/'; var supported_fields = [ @@ -22,6 +22,7 @@ angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', 'textarea', 'checkbox', 'date', + 'link', 'dropdown', 'hidden', 'password', @@ -34,10 +35,9 @@ angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', 'natural' ]; if (__indexOf.call(supported_fields, type) >= 0) { - templateUrl += type + '.html'; + templateUrl = templateUrl+type+'.html'; } - var template = $templateCache.get(templateUrl); - return template; + return templateUrl; }; var linker = function(scope, element) { @@ -53,24 +53,13 @@ angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', defaultDate: 0, }; } - //DAVID: TODO: Make natural language processing work - //Set only if we have a natural lang processing field - // else if(scope.field.fieldType === 'natural'){ - // scope.field.fieldMatchValue = ''; - // //Fires when field is changed - // scope.$watch('scope.field', function(newField, oldField) { - - // }); - // } - // GET template content from path - var template = getTemplateUrl(scope.field); - // $http.get(templateUrl).success(function(data) { - element.html(template).show(); - // console.log(element.contents()); - $compile(element.contents())(scope); - // }); + var templateUrl = getTemplateUrl(scope.field); + $http.get(templateUrl).success(function(data) { + element.html(data).show(); + $compile(element.contents())(scope); + }); }; return { diff --git a/public/modules/forms/directives/on-finish-render.client.directive.js b/public/modules/forms/directives/on-finish-render.client.directive.js index 01060462..07d62a33 100644 --- a/public/modules/forms/directives/on-finish-render.client.directive.js +++ b/public/modules/forms/directives/on-finish-render.client.directive.js @@ -13,10 +13,9 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo } var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; - - if(scope.$first) { + + if(scope.$first && !scope.$last) { scope.$evalAsync(function () { - // console.log(broadcastMessage+' Started'); // console.log(Date.now()); $rootScope.$broadcast(broadcastMessage+' Started'); }); diff --git a/public/modules/forms/services/forms.client.service.js b/public/modules/forms/services/forms.client.service.js index abae0c91..97bdb6e3 100644 --- a/public/modules/forms/services/forms.client.service.js +++ b/public/modules/forms/services/forms.client.service.js @@ -24,6 +24,7 @@ angular.module('forms').factory('Forms', ['$resource', method: 'GET', transformResponse: function(data, header) { var form = angular.fromJson(data); + console.log(form); form.visible_form_fields = _.filter(form.form_fields, function(field){ return (field.deletePreserved === false); diff --git a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js index 13e40a9a..46a2746a 100644 --- a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js @@ -72,6 +72,12 @@ }; }; + //Mock Users Service + beforeEach(module(function($provide) { + $provide.service('myForm', function($q) { + return sampleForm; + }); + })); // The $resource service augments the response object with methods for updating and deleting the resource. diff --git a/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js b/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js index c936881c..0d5ae113 100644 --- a/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js @@ -82,6 +82,14 @@ beforeEach(module('stateMock')); + //Mock Users Service + beforeEach(module(function($provide) { + $provide.service('myForm', function($q) { + return sampleForm; + }); + })); + + // 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. diff --git a/public/modules/forms/tests/unit/controllers/submit-form.client.controller.test.js b/public/modules/forms/tests/unit/controllers/submit-form.client.controller.test.js index bc5b80f0..f9194e2a 100644 --- a/public/modules/forms/tests/unit/controllers/submit-form.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/submit-form.client.controller.test.js @@ -41,6 +41,13 @@ ], }; + //Mock Users Service + beforeEach(module(function($provide) { + $provide.service('myForm', function($q) { + return sampleForm; + }); + })); + //Mock Users Service beforeEach(module(function($provide) { $provide.service('User', function($q) { @@ -206,7 +213,7 @@ })); - it('$scope.initForm() should populate $scope.myform with current Form', inject(function(Forms) { + it('on controller instantiation it should populate $scope.myform with current Form', inject(function(Forms) { var controller = createSubmitFormController(); @@ -215,13 +222,8 @@ // Set GET response $httpBackend.expectGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - // Run controller functionality - scope.initForm(); - $httpBackend.flush(); - $state.ensureAllTransitionsHappened(); - // Test scope value - expect( scope.myform.toJSON() ).toEqualData(sampleForm); + expect( scope.myform ).toEqualData(sampleForm); expect( scope.hideNav ).toEqual(false); })); }); diff --git a/public/modules/forms/tests/unit/directives/configure-form.client.directive.test.js b/public/modules/forms/tests/unit/directives/configure-form.client.directive.test.js index 23395ef4..f4ab2105 100644 --- a/public/modules/forms/tests/unit/directives/configure-form.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/configure-form.client.directive.test.js @@ -1,4 +1,3 @@ -'use strict'; (function() { // Forms Controller Spec diff --git a/public/modules/forms/views/admin-form.client.view.html b/public/modules/forms/views/admin-form.client.view.html index dd2dd0e8..5cd06aea 100644 --- a/public/modules/forms/views/admin-form.client.view.html +++ b/public/modules/forms/views/admin-form.client.view.html @@ -1,4 +1,4 @@ -
+