diff --git a/app.json b/app.json index e76cd024..36ae03d7 100644 --- a/app.json +++ b/app.json @@ -28,5 +28,10 @@ "description": "Which mail service/API you will be using (i.e. SparkPost, Mandrill, etc)", "value": "SendGrid" } - } + }, + "buildpacks": [ + { + "url": "https://github.com/heroku/heroku-buildpack-nodejs#v111" + } + ] } diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index ea148387..7b35eaff 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -10,7 +10,13 @@ var mongoose = require('mongoose'), config = require('../../config/config'), diff = require('deep-diff'), _ = require('lodash'), - helpers = require('./helpers.server.controller'); + nodemailer = require('nodemailer'), + emailNotifications = require('../libs/send-email-notifications'), + constants = require('../libs/constants'), + helpers = require('./helpers.server.controller'), + async = require('async'); + +var smtpTransport = nodemailer.createTransport(config.mailer.options); /** * Delete a forms submissions @@ -70,7 +76,51 @@ exports.createSubmission = function(req, res) { message: errorHandler.getErrorMessage(err) }); } - res.status(200).send('Form submission successfully saved'); + var form = req.body + var formFieldDict = emailNotifications.createFieldDict(form.form_fields); + + async.waterfall([ + function(callback) { + if (form.selfNotifications && form.selfNotifications.enabled && form.selfNotifications.fromField) { + form.selfNotifications.fromEmails = formFieldDict[form.selfNotifications.fromField]; + + emailNotifications.send(form.selfNotifications, formFieldDict, smtpTransport, constants.varFormat, function(err){ + if(err){ + return callback({ + message: 'Failure sending submission self-notification email' + }); + } + + callback(); + }); + } else { + callback(); + } + }, + function(callback) { + if (form.respondentNotifications && form.respondentNotifications.enabled && form.respondentNotifications.toField) { + + form.respondentNotifications.toEmails = formFieldDict[form.respondentNotifications.toField]; + debugger; + emailNotifications.send(form.respondentNotifications, formFieldDict, smtpTransport, constants.varFormat, function(err){ + if(err){ + return callback({ + message: 'Failure sending submission respondent-notification email' + }); + } + + callback(); + }); + } else { + callback(); + } + } + ], function (err) { + if(err){ + return res.status(400).send(err); + } + res.status(200).send('Form submission successfully saved'); + }); }); }; @@ -224,14 +274,13 @@ exports.getVisitorData = function(req, res) { * Create a new form */ exports.create = function(req, res) { - if(!req.body.form){ return res.status(400).send({ message: 'Invalid Input' }); } + var form = new Form(req.body.form); - form.admin = req.user._id; form.save(function(err, createdForm) { @@ -302,7 +351,7 @@ exports.update = function(req, res) { form.analytics = { visitors: [], gaCode: '' - } + }; } if (req.body.changes) { @@ -432,7 +481,7 @@ exports.formByIDFast = function(req, res, next, id) { } Form.findById(id) .lean() - .select('title language form_fields startPage endPage hideFooter isLive design analytics.gaCode') + .select('title language form_fields startPage endPage hideFooter isLive design analytics.gaCode selfNotifications respondentNotifications') .exec(function(err, form) { if (err) { return next(err); diff --git a/app/controllers/helpers.server.controller.js b/app/controllers/helpers.server.controller.js index 42499b92..f769187f 100644 --- a/app/controllers/helpers.server.controller.js +++ b/app/controllers/helpers.server.controller.js @@ -1,3 +1,5 @@ +'use strict'; + module.exports = { removeSensitiveModelData: function(type, object){ var privateFields = { @@ -5,7 +7,7 @@ module.exports = { 'private_form': ['__v'], 'public_user': ['passwordHash', 'password', 'provider', 'salt', 'lastModified', 'created', 'resetPasswordToken', 'resetPasswordExpires', 'token', 'apiKey', '__v'], 'private_user': ['passwordHash', 'password', 'provider', 'salt', 'resetPasswordToken', 'resetPasswordExpires', 'token', '__v'] - } + }; function removeKeysFromDict(dict, keys){ for(var i=0; i()\[\]\\.,;:\s@']+(\.[^<>()\[\]\\.,;:\s@']+)*)|('.+'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ - } + email: /^(([^<>()\[\]\\.,;:\s@']+(\.[^<>()\[\]\\.,;:\s@']+)*)|('.+'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + templateVariable: /(.|\n)*?<\/var>/g + }, + + varFormat: [']+)id=["\']{1}field:', '["\']{1}>([^<>]+)*?<\/var>'], }; \ No newline at end of file diff --git a/app/libs/send-email-notifications.js b/app/libs/send-email-notifications.js new file mode 100644 index 00000000..30af3aad --- /dev/null +++ b/app/libs/send-email-notifications.js @@ -0,0 +1,44 @@ +'use strict'; + +module.exports = { + send: function(emailSettings, emailTemplateVars, smtpTransport, varFormat, cb){ + var parsedTemplate = this.parseTemplate(emailSettings.htmlTemplate, emailTemplateVars, varFormat); + var parsedSubject = this.parseTemplate(emailSettings.subject, emailTemplateVars, varFormat); + var mailOptions = { + replyTo: emailSettings.fromEmails, + from: 'noreply@tellform.com', + cc: emailSettings.toEmails, + subject: parsedSubject, + html: parsedTemplate + }; + + console.log('HERE'); + smtpTransport.sendMail(mailOptions, function(){ + console.log('THERE'); + cb(); + }); + }, + + parseTemplate: function(emailTemplate, emailAttrs, varFormat){ + var resolvedTemplate = emailTemplate; + var that = this; + Object.keys(emailAttrs).forEach(function (key) { + resolvedTemplate = that.replaceTemplateVal(key, emailAttrs[key], resolvedTemplate, varFormat); + }); + return resolvedTemplate; + }, + + replaceTemplateVal: function(key, val, template, varFormat){ + return template.replace( new RegExp(varFormat[0] + key + varFormat[1], 'g'), val); + }, + + createFieldDict: function(form_fields){ + var formFieldDict = {}; + form_fields.forEach(function(field){ + if(field.hasOwnProperty('globalId') && field.hasOwnProperty('fieldValue')){ + formFieldDict[field.globalId] = field.fieldValue; + } + }); + return formFieldDict; + } +}; \ No newline at end of file diff --git a/app/libs/timestamp.server.plugin.js b/app/libs/timestamp.server.plugin.js index 084e2c1b..bba1649d 100644 --- a/app/libs/timestamp.server.plugin.js +++ b/app/libs/timestamp.server.plugin.js @@ -2,38 +2,36 @@ // Plugin module.exports = function timestamp (schema, options) { - options || (options = {}) + options = options || (options === {}); // Options - var fields = {} - , createdPath = options.createdPath || 'created' - , modifiedPath = options.modifiedPath || 'modified' - , useVirtual = (options.useVirtual !== undefined) - ? options.useVirtual - : true + var fields = {}, + createdPath = options.createdPath || 'created', + modifiedPath = options.modifiedPath || 'modified', + useVirtual = (options.useVirtual !== undefined) ? options.useVirtual : true; // Add paths to schema if not present if (!schema.paths[createdPath]) { - fields[modifiedPath] = { type: Date } + fields[modifiedPath] = { type: Date }; } if (useVirtual) { // Use the ObjectID for extracting the created time schema.virtual(createdPath).get(function () { - return new Date(this._id.generationTime * 1000) - }) + return new Date(this._id.generationTime * 1000); + }); } else { if (!schema.paths[createdPath]) { fields[createdPath] = { - type: Date - , default: Date.now - } + type: Date, + default: Date.now + }; } } - schema.add(fields) + schema.add(fields); // Update the modified timestamp on save schema.pre('save', function (next) { - this[modifiedPath] = new Date - next() - }) -} \ No newline at end of file + this[modifiedPath] = new Date(); + next(); + }); +}; \ No newline at end of file diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 45248df1..236d0ddd 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -7,7 +7,8 @@ var mongoose = require('mongoose'), Schema = mongoose.Schema, _ = require('lodash'), timeStampPlugin = require('../libs/timestamp.server.plugin'), - async = require('async'); + async = require('async'), + constants = require('../libs/constants'); //Mongoose Models var FieldSchema = require('./form_field.server.model.js'); @@ -52,11 +53,12 @@ var VisitorDataSchema = new Schema({ type: Boolean }, language: { - type: String + type: String, + enum: constants.languageTypes, + default: 'en', }, ipAddr: { - type: String, - default: '' + type: String }, deviceType: { type: String, @@ -149,6 +151,47 @@ var FormSchema = new Schema({ buttons:[ButtonSchema] }, + selfNotifications: { + fromField: { + type: String + }, + toEmails: { + type: String + }, + subject: { + type: String + }, + htmlTemplate: { + type: String + }, + enabled: { + type: Boolean, + default: false + } + }, + + respondentNotifications: { + toField: { + type: String + }, + fromEmails: { + type: String, + match: [/.+\@.+\..+/, 'Please fill a valid email address'] + }, + subject: { + type: String, + default: 'Tellform: Thank you for filling out this TellForm' + }, + htmlTemplate: { + type: String, + default: 'Hello,

We’ve received your submission.

Thank you & have a nice day!', + }, + enabled: { + type: Boolean, + default: false + } + }, + hideFooter: { type: Boolean, default: false diff --git a/app/models/form_field.server.model.js b/app/models/form_field.server.model.js index 31f96e71..4df9c741 100644 --- a/app/models/form_field.server.model.js +++ b/app/models/form_field.server.model.js @@ -9,7 +9,8 @@ var mongoose = require('mongoose'), _ = require('lodash'), Schema = mongoose.Schema, LogicJumpSchema = require('./logic_jump.server.model'), - tokgen = require('../libs/tokenGenerator'); + tokgen = require('../libs/tokenGenerator'), + constants = require('../libs/constants'); var FieldOptionSchema = new Schema({ option_id: { @@ -34,21 +35,7 @@ var RatingFieldSchema = new Schema({ }, shape: { type: String, - enum: [ - 'Heart', - 'Star', - 'thumbs-up', - 'thumbs-down', - 'Circle', - 'Square', - 'Check Circle', - 'Smile Outlined', - 'Hourglass', - 'bell', - 'Paper Plane', - 'Comment', - 'Trash' - ] + enum: constants.ratingShapeTypes }, validShapes: { type: [String] @@ -103,29 +90,7 @@ function BaseFieldSchema(){ }, fieldType: { type: String, - enum: [ - 'textfield', - 'date', - 'email', - 'link', - 'legal', - 'url', - 'textarea', - 'statement', - 'welcome', - 'thankyou', - 'file', - 'dropdown', - 'scale', - 'rating', - 'radio', - 'checkbox', - 'hidden', - 'yes_no', - 'natural', - 'stripe', - 'number' - ] + enum: constants.fieldTypes }, fieldValue: Schema.Types.Mixed }); @@ -140,7 +105,7 @@ function BaseFieldSchema(){ this.validFieldTypes = mongoose.model('Field').schema.path('fieldType').enumValues; if(this.fieldType === 'rating' && this.ratingOptions.validShapes.length === 0){ - this.ratingOptions.validShapes = mongoose.model('RatingOptions').schema.path('shape').enumValues; + this.ratingOptions.validShapes = constants.ratingShapeTypes; } next(); diff --git a/app/models/form_submission.server.model.js b/app/models/form_submission.server.model.js index a3505f3a..6e77529f 100644 --- a/app/models/form_submission.server.model.js +++ b/app/models/form_submission.server.model.js @@ -55,18 +55,18 @@ FormSubmissionSchema.pre('save', function (next) { this.form_fields[i].fieldValue = this.form_fields[i].fieldValue.option_value; } - delete form_fields[i].validFieldTypes; - delete form_fields[i].disabled; - delete form_fields[i].required; - delete form_fields[i].isSubmission; - delete form_fields[i].title; - delete form_fields[i].fieldOptions; - delete form_fields[i].ratingOptions; - delete form_fields[i].logicJump; - delete form_fields[i].description; - delete form_fields[i].created; - delete form_fields[i].lastModified; - delete form_fields[i].deletePreserved; + delete this.form_fields[i].validFieldTypes; + delete this.form_fields[i].disabled; + delete this.form_fields[i].required; + delete this.form_fields[i].isSubmission; + delete this.form_fields[i].title; + delete this.form_fields[i].fieldOptions; + delete this.form_fields[i].ratingOptions; + delete this.form_fields[i].logicJump; + delete this.form_fields[i].description; + delete this.form_fields[i].created; + delete this.form_fields[i].lastModified; + delete this.form_fields[i].deletePreserved; } next(); }); diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index ab1d35b0..395ac080 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -9,19 +9,7 @@ var mongoose = require('mongoose'), config = require('../../config/config'), timeStampPlugin = require('../libs/timestamp.server.plugin'), path = require('path'), - querystring = require('querystring'), - nodemailer = require('nodemailer'); - -var smtpTransport = nodemailer.createTransport(config.mailer.options); - -// verify connection configuration on startup -smtpTransport.verify(function(error, success) { - if (error) { - console.log('Your mail configuration is incorrect', error); - } else { - console.log('Mail server is ready to take our messages'); - } -}); + querystring = require('querystring'); /** * User Schema @@ -42,7 +30,7 @@ var UserSchema = new Schema({ trim: true, lowercase: true, unique: 'Account already exists with this email', - match: [/.+\@.+\..+/, 'Please fill a valid email address'], + match: [constants.regex.email, 'Please fill a valid email address'], required: [true, 'Email is required'] }, username: { @@ -66,13 +54,13 @@ var UserSchema = new Schema({ roles: { type: [{ type: String, - enum: ['user', 'admin', 'superuser'] + enum: constants.userRoleTypes }], default: ['user'] }, language: { type: String, - enum: ['en', 'fr', 'es', 'it', 'de'], + enum: constants.languageTypes, default: 'en', }, lastModified: { diff --git a/app/routes/forms.server.routes.js b/app/routes/forms.server.routes.js index 123ce644..7d2e3e14 100644 --- a/app/routes/forms.server.routes.js +++ b/app/routes/forms.server.routes.js @@ -31,7 +31,7 @@ module.exports = function(app) { } app.route('/forms/:formIdFast([a-zA-Z0-9]+)') - .post(forms.createSubmission) + .post(forms.createSubmission); app.route('/forms') .get(auth.isAuthenticatedOrApiKey, forms.list) diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index 1ed05b06..a4c16889 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -166,7 +166,7 @@ describe('Form Routes Unit tests', function() { it(' > should not be able to create a Form if body is empty', function(done) { loginSession.post('/forms') .send({form: null}) - .expect(400, {"message":"Invalid Input"}) + .expect(400, {'message':'Invalid Input'}) .end(function(FormSaveErr, FormSaveRes) { // Call the assertion callback done(FormSaveErr); diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index d7874e5c..262fbf04 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -81,8 +81,8 @@ describe('FormSubmission Model Unit Tests:', function() { user = new User({ firstName: 'Full', lastName: 'Name', - email: 'test1@test.com'+Date.now(), - username: 'test1'+Date.now(), + email: 'test1@test.com', + username: 'test1', password: 'password', provider: 'local' }); diff --git a/app/tests/form_submission.routes.test.js b/app/tests/form_submission.routes.test.js index 13d5e780..6398828e 100644 --- a/app/tests/form_submission.routes.test.js +++ b/app/tests/form_submission.routes.test.js @@ -21,15 +21,14 @@ var credentials, user; * Form routes tests */ describe('Form Submission Routes Unit tests', function() { - var FormObj, _Submission, submissionSession, _SubmissionBody - + var FormObj, _Submission, submissionSession, _SubmissionBody; beforeEach(function(done) { // Create user credentials credentials = { - email: 'test@test.com', - username: 'test', + email: 'test423@test.com', + username: 'test534', password: 'password' }; @@ -45,7 +44,10 @@ describe('Form Submission Routes Unit tests', function() { // Save a user to the test db and create new Form user.save(function(err) { - if(err) return done(err); + if(err) { + return done(err); + } + FormObj = new Form({ title: 'Form Title', language: 'en', @@ -54,7 +56,22 @@ describe('Form Submission Routes Unit tests', function() { new Field({'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}), new Field({'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}), new Field({'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''}) - ] + ], + selfNotifications: { + fromField: mongoose.Types.ObjectId(), + toEmails: 'john@smith.com', + subject: 'Hello there', + htmlTemplate: '

A form was submitted

', + enabled: true + }, + + respondentNotifications: { + toField: mongoose.Types.ObjectId(), + fromEmails: 'john@smith.com', + subject: 'Tellform: Thank you for filling out this TellForm', + htmlTemplate:'Hello,

We’ve received your submission.

Thank you & have a nice day!', + enabled: true + } }); FormObj.save(function(formSaveErr, form) { @@ -237,6 +254,4 @@ describe('Form Submission Routes Unit tests', function() { }); }); }); - - }); diff --git a/app/tests/libs/send-email-notifications.test.js b/app/tests/libs/send-email-notifications.test.js new file mode 100644 index 00000000..10f8d98f --- /dev/null +++ b/app/tests/libs/send-email-notifications.test.js @@ -0,0 +1,94 @@ +'use strict'; + +/** + * Module dependencies. + */ +const emailNotifications = require('../../libs/send-email-notifications'), + constants = require('../../libs/constants'), + mockTransport = require("nodemailer").createTransport("Stub"), + config = require('../../../config/config'); + +/** + * Globals + */ +const validFormFields = [ + {fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false, globalId:'56340745f59a6fc9e22028e9'}, + {fieldType:'link', title:'Your Website', fieldValue: 'https://johnsmith.me', deletePreserved: false, globalId:'5c9e22028e907634f45f59a6'}, + {fieldType:'number', title:'Your Age', fieldValue: 45, deletePreserved: false, globalId:'56e90745f5934fc9e22028a6'} +]; + +const validFieldDict = { + '56340745f59a6fc9e22028e9': 'John Smith', + '5c9e22028e907634f45f59a6': 'https://johnsmith.me', + '56e90745f5934fc9e22028a6': 45 +}; + +const invalidFormFields = [ + {fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false}, + {fieldType:'link', title:'Your Website', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, + {fieldType:'number', title:'Your Age'} +]; + +const htmlTemplate = '

First Name \ +
Your Website \ +
Your Age

'; + +const renderedTemplate = '

John Smith \ +
https://johnsmith.me \ +
45

'; + +/** + * Unit tests + */ +describe('Send Email Notification Unit Tests', function() { + + describe('Method createFieldDict', function() { + it('should be return a fieldDict from valid form fields', function() { + var actualFieldDict = emailNotifications.createFieldDict(validFormFields); + actualFieldDict.should.deepEqual(validFieldDict); + }); + + it('should return empty object if form fields are invalid or empty ', function() { + var actualFieldDict = emailNotifications.createFieldDict(invalidFormFields); + actualFieldDict.should.be.empty(); + }); + }); + + describe('Method parseTemplate', function(){ + it('should properly render a template given a valid field dict', function() { + var actualRenderedTemplate = emailNotifications.parseTemplate(htmlTemplate, validFieldDict, constants.varFormat).replace((/ |\r\n|\n|\r|\t/gm),''); + actualRenderedTemplate.should.equal(renderedTemplate.replace((/ |\r\n|\n|\r|\t/gm),'')); + }); + }); + + describe('Method replaceTemplateVal', function() { + it('should properly replace a template var in a valid template', function() { + var expectedHtml = '

John Smith \ +
Your Website \ +
Your Age

'; + + var actualRenderedTemplate = emailNotifications.replaceTemplateVal('56340745f59a6fc9e22028e9', validFieldDict['56340745f59a6fc9e22028e9'], htmlTemplate, constants.varFormat).replace((/ |\r\n|\n|\r|\t/gm),''); + actualRenderedTemplate.should.equal(expectedHtml.replace((/ |\r\n|\n|\r|\t/gm),'')); + }); + }); + + describe('Method send', function() { + this.timeout(10000); + const emailSettings = { + fromEmails: 'somewhere@somewhere.com', + toEmails: 'there@there.com', + subject: 'Hello First Name!', + htmlTemplate: htmlTemplate + }; + + const emailTemplateVars = validFieldDict; + const varFormat = constants.varFormat; + + it('should properly replace a template var in a valid template', function(done) { + emailNotifications.send(emailSettings, emailTemplateVars, mockTransport, varFormat, function(err){ + should.not.exist(err); + done(); + }); + }); + }); +}); diff --git a/app/tests/libs/timestamp.server.plugin.test.js b/app/tests/libs/timestamp.server.plugin.test.js index 2901fe72..d943ec27 100644 --- a/app/tests/libs/timestamp.server.plugin.test.js +++ b/app/tests/libs/timestamp.server.plugin.test.js @@ -1,70 +1,72 @@ +'use strict'; + // Dependencies -var util = require('util') - , assert = require('assert') - , mongoose = require('mongoose') - , timestamp = require('../../libs/timestamp.server.plugin') - , Schema = mongoose.Schema - , ObjectId = Schema.ObjectId +var util = require('util'), + assert = require('assert'), + mongoose = require('mongoose'), + timestamp = require('../../libs/timestamp.server.plugin'), + Schema = mongoose.Schema, + ObjectId = Schema.ObjectId; // Run tests describe('Timestamp', function () { describe('#default()', function () { - var FooSchema = new Schema() - FooSchema.plugin(timestamp) - var FooModel = mongoose.model('timeFoo', FooSchema) - , bar = new FooModel() + var FooSchema = new Schema(); + FooSchema.plugin(timestamp); + var FooModel = mongoose.model('timeFoo', FooSchema), + bar = new FooModel(); before(function () { FooModel.remove(function (err) { - assert.strictEqual(err, null) - }) - }) + assert.strictEqual(err, null); + }); + }); it('should have custom properties', function (done) { - assert.strictEqual(typeof FooSchema.virtuals.created, 'object') - assert.strictEqual(typeof FooSchema.paths.modified, 'object') - done() - }) + assert.strictEqual(typeof FooSchema.virtuals.created, 'object'); + assert.strictEqual(typeof FooSchema.paths.modified, 'object'); + done(); + }); it('should create the default attributes', function (done) { bar.save(function (err, doc) { - assert.strictEqual(err, null) - assert.strictEqual(util.isDate(doc.created), true) - assert.strictEqual(util.isDate(doc.modified), true) - done() - }) - }) - }) + assert.strictEqual(err, null); + assert.strictEqual(util.isDate(doc.created), true); + assert.strictEqual(util.isDate(doc.modified), true); + done(); + }); + }); + }); describe('#custom()', function () { - var FooSchema = new Schema() + var FooSchema = new Schema(); FooSchema.plugin(timestamp, { - createdPath: 'oh' - , modifiedPath: 'hai' - , useVirtual: false - }) - var BarModel = mongoose.model('timeBar', FooSchema) - , bar = new BarModel() + createdPath: 'oh', + modifiedPath: 'hai', + useVirtual: false + }); + var BarModel = mongoose.model('timeBar', FooSchema), + bar = new BarModel(); before(function () { BarModel.remove(function (err) { - assert.strictEqual(err, null) - }) - }) + assert.strictEqual(err, null); + }); + }); it('should have custom properties', function (done) { - assert.strictEqual(typeof FooSchema.paths.oh, 'object') - assert.strictEqual(typeof FooSchema.paths.hai, 'object') - done() - }) + assert.strictEqual(typeof FooSchema.paths.oh, 'object'); + assert.strictEqual(typeof FooSchema.paths.hai, 'object'); + done(); + }); it('should create custom attributes', function (done) { bar.save(function (err, doc) { - assert.strictEqual(err, null) - assert.strictEqual(util.isDate(doc.oh), true) - assert.strictEqual(util.isDate(doc.hai), true) - done() - }) - }) - }) -}) \ No newline at end of file + assert.strictEqual(err, null); + assert.strictEqual(util.isDate(doc.oh), true); + assert.strictEqual(util.isDate(doc.hai), true); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 12b7af76..7198d449 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -48,7 +48,7 @@ describe('User CRUD tests', function() { .send(_User) .expect(200) .end(function(err) { - callback(err) + callback(err); }); }, function(callback) { @@ -136,7 +136,7 @@ describe('User CRUD tests', function() { if(err){ callback(err); } - callback(null, user.resetPasswordToken) + callback(null, user.resetPasswordToken); }); }, function(resetPasswordToken, callback) { diff --git a/app/views/form.server.view.pug b/app/views/form.server.view.pug index 451536e7..2c44f399 100644 --- a/app/views/form.server.view.pug +++ b/app/views/form.server.view.pug @@ -78,13 +78,15 @@ html(lang='en', xmlns='http://www.w3.org/1999/xhtml') //Socket.io Client Dependency script(src='/static/lib/socket.io-client/dist/socket.io.min.js') - script(src='/static/lib/jquery-ui/jquery-ui.js', type='text/javascript') //Minified Bower Dependencies script(src='/static/lib/angular/angular.min.js') script(src='/static/dist/vendor.min.js') script(src='/static/lib/angular-ui-date/src/date.js', type='text/javascript') + script(src='/static/lib/jquery-ui/jquery-ui.js', type='text/javascript') + script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', integrity='sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa', crossorigin='anonymous') + //Application JavaScript Files each jsFile in formJSFiles script(type='text/javascript', src=jsFile) diff --git a/app/views/index.server.view.pug b/app/views/index.server.view.pug index 10c29935..0d0c17fc 100644 --- a/app/views/index.server.view.pug +++ b/app/views/index.server.view.pug @@ -3,7 +3,9 @@ extends layout.server.view.pug block content section.content(ui-view='', ng-cloak='') - script(src='/static/lib/file-saver.js/FileSaver.js', type='text/javascript') + + link(rel='stylesheet', href='/static/lib/jquery-ui/themes/flick/jquery-ui.min.css') + script(src='/static/lib/jquery/jquery.min.js') //Embedding The User Object script(type='text/javascript'). diff --git a/app/views/layout.server.view.pug b/app/views/layout.server.view.pug index 39ba97d5..7509f3a2 100644 --- a/app/views/layout.server.view.pug +++ b/app/views/layout.server.view.pug @@ -31,8 +31,8 @@ html(lang='en', xmlns='http://www.w3.org/1999/xhtml') // Fav Icon link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon') - link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css') - link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u', crossorigin='anonymous') + link(rel='stylesheet', href='/static/lib/font-awesome/css/font-awesome.min.css') + link(rel='stylesheet', href='/static/lib/bootstrap/dist/css/bootstrap.min.css') link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900') //Bower CSS dependencies @@ -40,7 +40,6 @@ html(lang='en', xmlns='http://www.w3.org/1999/xhtml') link(rel='stylesheet', href=bowerCssFile) link(rel='stylesheet', href='/static/lib/angular-input-stars/angular-input-stars.css') link(rel='stylesheet', href='/static/lib/jquery-ui/themes/flick/jquery-ui.css') - link(rel='stylesheet', href='/static/modules/core/css/github-fork-ribbon.css') // end Bower CSS dependencies //Application CSS Files diff --git a/bower.json b/bower.json index afdaec71..4336c3ac 100755 --- a/bower.json +++ b/bower.json @@ -25,7 +25,6 @@ "angular-permission": "~1.1.1", "file-saver.js": "~1.20150507.2", "angular-bootstrap-colorpicker": "~3.0.19", - "angular-ui-router-tabs": "~1.7.0", "angular-scroll": "^1.0.0", "angular-sanitize": "1.4.14", "v-button": "^1.1.1", @@ -33,7 +32,6 @@ "raven-js": "^3.0.4", "tableExport.jquery.plugin": "^1.5.1", "js-yaml": "^3.6.1", - "angular-ui-select": "https://github.com/tellform/ui-select.git#compiled", "angular-translate": "~2.11.0", "ng-translate": "*", "deep-diff": "^0.3.4", @@ -42,17 +40,22 @@ "mobile-detect": "^1.3.3", "socket.io-client": "^1.7.2", "css-toggle-switch": "^4.0.2", - "angular-strap": "^2.3.12" + "angular-strap": "^2.3.12", + "textAngular": "^1.5.16", + "angular-ui-select": "^0.19.8", + "angular-bootstrap-switch": "^0.5.2", + "jquery": "^3.2.1" }, "resolutions": { "angular-bootstrap": "^0.14.0", "angular": "1.4.14", - "angular-ui-select": "compiled", "jspdf": "~1.0.178", "angular-sanitize": "1.4.14", "angular-ui-sortable": "^0.17.1", "angular-ui-date": "~0.0.11", - "angular-input-stars-directive": "master" + "angular-input-stars-directive": "master", + "angular-ui-select": "^0.19.8", + "jquery": "^3.2.1" }, "overrides": { "BOWER-PACKAGE": { diff --git a/config/express.js b/config/express.js index ae73bf16..99357774 100755 --- a/config/express.js +++ b/config/express.js @@ -39,8 +39,9 @@ var configureSocketIO = function (app, db) { var supportedLanguages = ['en', 'de', 'fr', 'it', 'es']; function containsAnySupportedLanguages(preferredLanguages){ - for (var i = 0; i < preferredLanguages.length; i++) { - var currIndex = supportedLanguages.indexOf(preferredLanguages[i]); + var i, currIndex; + for (i = 0; i < preferredLanguages.length; i++) { + currIndex = supportedLanguages.indexOf(preferredLanguages[i]); if (currIndex > -1) { return supportedLanguages[currIndex]; } @@ -226,7 +227,6 @@ module.exports = function(db) { // Setting the app router and static folder app.use('/static', express.static(path.resolve('./public'))); - app.use('/uploads', express.static(path.resolve('./uploads'))); // CookieParser should be above session app.use(cookieParser()); @@ -261,6 +261,7 @@ module.exports = function(db) { //Visitor Language Detection app.use(function(req, res, next) { var acceptLanguage = req.headers['accept-language']; + var languages, supportedLanguage; if(acceptLanguage){ @@ -270,13 +271,12 @@ module.exports = function(db) { if(!req.user && supportedLanguage !== null){ var currLanguage = res.cookie('userLang'); - if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){ res.clearCookie('userLang'); res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true }); + } else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies.userLang !== req.user.language) ){ + res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true }); } - } else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies['userLang'] !== req.user.language) ){ - res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true }); } next(); }); diff --git a/dump.rdb b/dump.rdb new file mode 100644 index 00000000..c6e61e2a Binary files /dev/null and b/dump.rdb differ diff --git a/gruntfile.js b/gruntfile.js index 943dc796..ad0e35b8 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -1,4 +1,4 @@ - +'use strict'; var bowerArray = ['public/lib/angular/angular.min.js', 'public/lib/angular-scroll/angular-scroll.min.js', diff --git a/package-lock.json b/package-lock.json index 25d97ec8..ab46ade9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3129,13 +3129,10 @@ } }, "connect-mongo": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-0.8.2.tgz", - "integrity": "sha1-ySh47sDFpaZiW3mgwhTzf4YfxuA=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.0.tgz", + "integrity": "sha512-2Nj5d4XO55AXSy1GOXDZteSEEUObGm/kvJaXyEQCa8cCHsCiZH+V/+sjk3b+khc4V8oyVi34rCtUxor4TfETLA==", "requires": { - "debug": "3.1.0", - "depd": "1.1.1", - "lodash": "4.17.4", "mongodb": "2.0.55" } }, @@ -4415,6 +4412,15 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, "extendr": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/extendr/-/extendr-2.1.0.tgz", @@ -6286,6 +6292,301 @@ } } }, + "grunt-lcov-merge": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/grunt-lcov-merge/-/grunt-lcov-merge-1.2.3.tgz", + "integrity": "sha1-hGb401OfCItGSaYP/F7dLeklVBE=", + "dev": true, + "requires": { + "async": "2.5.0", + "chalk": "1.1.3", + "lcov-result-merger": "1.2.0", + "through2": "0.6.5", + "vinyl": "1.2.0", + "vinyl-fs": "2.4.4" + }, + "dependencies": { + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + } + } + }, "grunt-legacy-log": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", @@ -6454,6 +6755,44 @@ "wiredep": "4.0.0" } }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, "gzip-size": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", @@ -7302,6 +7641,12 @@ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -7950,6 +8295,15 @@ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -7965,6 +8319,185 @@ "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, + "lcov-result-merger": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lcov-result-merger/-/lcov-result-merger-1.2.0.tgz", + "integrity": "sha1-XeHmQm+IWSm3c1fwFN5f7h2tBVM=", + "dev": true, + "requires": { + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-fs": "2.4.4" + }, + "dependencies": { + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + } + } + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -8177,6 +8710,12 @@ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -9644,6 +10183,12 @@ "no-case": "2.3.2" } }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -10697,6 +11242,12 @@ "is-finite": "1.0.2" } }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, "request": { "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", @@ -11444,6 +11995,16 @@ "is-utf8": "0.2.1" } }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -11687,6 +12248,15 @@ "os-tmpdir": "1.0.2" } }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, "to-array": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", @@ -12023,6 +12593,12 @@ } } }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", diff --git a/package.json b/package.json index 377f41ff..6954a85a 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,7 @@ "generate": "all-contributors generate", "start": "grunt", "test": "grunt test", - "travis": "grunt test:travis", - "postinstall": "bower install --config.interactive=false; grunt build;", + "postinstall": "bower install --config.interactive=false", "init": "node scripts/setup.js" }, "dependencies": { @@ -32,7 +31,7 @@ "chalk": "^1.1.3", "compression": "~1.6.0", "connect": "^3.4.1", - "connect-mongo": "~0.8.2", + "connect-mongo": "^2.0.0", "consolidate": "~0.14.5", "cookie-parser": "~1.4.0", "deep-diff": "^0.3.4", @@ -42,7 +41,7 @@ "express": "~4.13.3", "express-session": "~1.12.1", "glob": "^7.0.3", - "grunt": "~0.4.1", + "grunt": "^0.4.5", "grunt-concurrent": "~2.3.0", "grunt-contrib-csslint": "~1.0.0", "grunt-contrib-cssmin": "~1.0.1", diff --git a/public/config.js b/public/config.js index d21482bf..dde967a4 100755 --- a/public/config.js +++ b/public/config.js @@ -4,7 +4,7 @@ var ApplicationConfiguration = (function() { // Init module configuration options var applicationModuleName = 'TellForm'; - var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'ngSanitize', 'vButton', 'ngResource', 'TellForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate', 'view-form']; + var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'ngSanitize', 'vButton', 'ngResource', 'TellForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate']; // Add a new vertical module var registerModule = function(moduleName, dependencies) { diff --git a/public/dist/application.js b/public/dist/application.js index 3d3aa5ae..ef026e57 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -4236,18 +4236,16 @@ angular.module('view-form').directive('keyToOption', function(){ 'use strict'; -angular.module('view-form').directive('keyToTruthy', ["$rootScope", function($rootScope){ - return { - restrict: 'A', - scope: { - field: '=', - nextField: '&' - }, - link: function($scope, $element, $attrs) { - $element.bind('keydown keypress', function(event) { - var keyCode = event.which || event.keyCode; - var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32; - var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32; +// Init the application configuration module for AngularJS application +var ApplicationConfiguration = (function() { + // Init module configuration options + var applicationModuleName = 'TellForm'; + var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'ngSanitize', 'vButton', 'ngResource', 'TellForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate']; + + // Add a new vertical module + var registerModule = function(moduleName, dependencies) { + // Create angular module + angular.module(moduleName, dependencies || []); if(keyCode === truthyKeyCode ) { event.preventDefault(); @@ -5102,8 +5100,6 @@ angular.module('view-form').directive('submitFormDirective', ["$http", "TimeCoun }; $rootScope.prevField = $scope.prevField = function(){ - console.log('prevField'); - console.log($scope.selected); var selected_index = $scope.selected.index - 1; if($scope.selected.index > 0){ $scope.setActiveField(null, selected_index, true); @@ -5197,17 +5193,6 @@ angular.module('view-form').directive('submitFormDirective', ["$http", "TimeCoun if($scope.myform.form_fields[i].fieldType === 'dropdown' && !$scope.myform.form_fields[i].deletePreserved){ $scope.myform.form_fields[i].fieldValue = $scope.myform.form_fields[i].fieldValue.option_value; } - - //Get rid of unnessecary attributes for each form field - delete form.form_fields[i].submissionId; - delete form.form_fields[i].disabled; - delete form.form_fields[i].ratingOptions; - delete form.form_fields[i].fieldOptions; - delete form.form_fields[i].logicJump; - delete form.form_fields[i].description; - delete form.form_fields[i].validFieldTypes; - delete form.form_fields[i].fieldType; - } setTimeout(function () { diff --git a/public/dist/application.min.css b/public/dist/application.min.css new file mode 100644 index 00000000..66157122 --- /dev/null +++ b/public/dist/application.min.css @@ -0,0 +1,4 @@ +.tag,.vcenter{vertical-align:middle}.navbar,.navbar-nav,.navbar-nav>li{min-height:60px}.image-background,.opacity-background{position:fixed;height:100%;width:100%;top:0;left:0}.btn-rounded,.field-title-row,section.auth .btn{text-transform:uppercase}.form-item .title-row>.list-group-item-heading{color:#34628a}.form-item.paused .title-row>.list-group-item-heading,.form-item:hover .title-row>.list-group-item-heading{color:#fff}.form-item:hover .title-row{text-decoration:none}body{overflow-x:hidden;font-family:'Source Sans Pro',sans-serif;font-size:16px}.vcenter{display:inline-block;float:none}.btn-rounded{border-radius:100px;font-size:14px;padding:10px 28px;margin:1em 2px 0;text-decoration:none!important}.current-fields .panel-heading a:hover,.current-fields .tool-panel.panel .panel-heading a:hover,.footer-basic-centered .footer-links a,.undecorated-link:hover{text-decoration:none}.btn-secondary{background:#DDD;color:#4c4c4c;border:2px solid #4c4c4c}.btn-secondary:hover{background:#cacaca;border-color:#cacaca}.navbar{padding:10px 0}.navbar-inverse{background-color:#3FA2F7;border:0;color:#fff!important}.navbar .navbar-brand{min-height:60px;padding:10px}.navbar-nav>li>a{padding-top:20px;color:#fff}.navbar-nav>li.active,.navbar-nav>li:hover{background-color:#4b7096}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:transparent;color:inherit;border:none}.navbar-inverse .navbar-nav>li>a{color:#fff}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#f9f9f9}.navbar-inverse .navbar-toggle{border:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.dropdown-menu>li>a{color:#515151}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{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{background-color:#000;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}.footer-basic-centered{background-color:#292c2f;box-shadow:0 1px 1px 0 rgba(0,0,0,.12);box-sizing:border-box;width:100%;text-align:center;font:400 18px sans-serif;padding:45px;margin-top:80px}.footer-basic-centered .footer-company-motto{color:#8d9093;font-size:24px;margin:0}.footer-basic-centered .footer-company-name{color:#8f9296;font-size:14px;margin:0}.footer-basic-centered .footer-links{list-style:none;font-weight:700;color:#fff;padding:35px 0 23px;margin:0}.footer-basic-centered .footer-links a{display:inline-block;color:inherit}@media (max-width:600px){.footer-basic-centered{padding:35px}.footer-basic-centered .footer-company-motto{font-size:18px}.footer-basic-centered .footer-company-name{font-size:12px}.footer-basic-centered .footer-links{font-size:14px;padding:25px 0 20px}.footer-basic-centered .footer-links a{line-height:1.8}}/*! + * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License + * https://github.com/simonwhitaker/github-fork-ribbon-css +*/.github-fork-ribbon{position:absolute;padding:2px 0;background-color:#a00;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-ms-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-o-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.15));-webkit-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);-moz-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);box-shadow:0 2px 3px 0 rgba(0,0,0,.5);font:700 13px "Helvetica Neue",Helvetica,Arial,sans-serif;z-index:9999;pointer-events:auto}.github-fork-ribbon a,.github-fork-ribbon a:hover{color:#fff;text-decoration:none;text-shadow:0 -1px rgba(0,0,0,.5);text-align:center;width:200px;line-height:20px;display:inline-block;padding:2px 0;border-width:1px 0;border-style:dotted;border-color:#fff;border-color:rgba(255,255,255,.7)}.github-fork-ribbon-wrapper{width:150px;height:150px;position:absolute;overflow:hidden;top:0;z-index:9998;pointer-events:none}.github-fork-ribbon-wrapper.fixed{position:fixed}.github-fork-ribbon-wrapper.left{left:0}.github-fork-ribbon-wrapper.right{right:0}.github-fork-ribbon-wrapper.left-bottom{position:fixed;top:inherit;bottom:0;left:0}.github-fork-ribbon-wrapper.right-bottom{position:fixed;top:inherit;bottom:0;right:0}.github-fork-ribbon-wrapper.right .github-fork-ribbon{top:42px;right:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.left .github-fork-ribbon{top:42px;left:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon{top:80px;left:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon{top:80px;right:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.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;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;-moz-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 option,.modal-header{font-weight:400}.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::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}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.tag{background-color:#999;border-radius:3px;border:0;color:#FFF;font-style:inherit;font-size:11px;padding:4px 5px;margin:0 2px 2px;font-family:inherit;white-space:nowrap;cursor:pointer!important;pointer-events:none}.email-subject .ta-scroll-window.form-control,.email-subject.ta-root .ta-editor.ta-html{min-height:0;overflow:hidden;height:auto;border-radius:4px;box-shadow:none;font-size:18px;padding-top:10px}.email-subject.ta-root .ta-scroll-window>.ta-bind{min-height:0;outline:0}.ui-select input.form-control{height:34px;padding:6px}.config-form .btn-secondary{border-color:#DDD}.notification-toggle.toggle-switch{margin:5px 0}.pull-top{display:inline-block;vertical-align:top;float:none}.nav.nav-pills.nav-stacked,div.tab-content{position:relative;min-height:1px;float:left}.box{padding:0 5px!important}.current-fields .field-row{padding:5px 0}.current-fields .panel{background-color:#f1f1f1;margin-top:0!important}.current-fields .panel:hover{background-color:#fff;cursor:pointer}.current-fields .panel.tool-panel{background-color:#fff}.current-fields .panel-heading{background-color:#f1f1f1;position:relative}.current-fields .panel-heading:hover{background-color:#fff;cursor:pointer}.current-fields .tool-panel.panel:hover{border-color:#9d9d9d;background-color:#eee;cursor:pointer}.current-fields .tool-panel.panel:hover .panel-heading{background-color:inherit;color:#000;cursor:pointer}.current-fields .tool-panel.panel .panel-heading{background-color:#fff;color:#9d9d9d}.current-fields .tool-panel.panel .panel-heading a{color:inherit}.nav.nav-pills.nav-stacked{width:16.66666667%;padding-right:15px}div.tab-content{width:83.33333333%;padding-top:0!important}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}.busy-updating-wrapper{text-align:center;font-size:20px;position:fixed;bottom:0;right:55px;z-index:1}.busy-submitting-wrapper{position:fixed;top:50%;left:0;right:0;bottom:0}.dropzone h4.panel-title{height:17px;overflow:hidden}.container.admin-form{margin-top:70px}.edit-modal-window .modal-dialog{width:90%}.edit-modal-window .modal-body{padding:0}.edit-modal-window .edit-panel{background-color:#F1F1F1;padding:0 35px}.edit-modal-window .preview-field-panel{display:flex;flex-direction:column;justify-content:center}.edit-modal-window .preview-field-panel form{padding-right:20px}.edit-modal-window .preview-field{resize:vertical}.admin-form .ui-sortable-placeholder{visibility:visible!important;border:none;padding:1px;background:rgba(0,0,0,.5)!important}.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);-moz-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.design>.row>.container:nth-of-type(odd){border-right:none}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;margin-top:none;margin-bottom:none}.admin-form .tab-content{padding-top:3em}.submissions-table .table-outer.row{margin:1.5em 0 2em!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}.admin-form .oscar-field-select{margin:10px 0}.view-form-btn{border:none}.view-form-btn.span{padding-right:.6em}.notification-row{display:inline-block;padding:0 5px}.status-light{font-size:10px}.notification-row .status-light{padding-top:15px}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}.analytics .header-title{font-size:1em;color:#bab8b8}.analytics .header-numbers{font-size:4em;padding-bottom:.1em;margin-bottom:.5em;border-bottom:#fafafa solid 1px}.analytics .detailed-title{font-size:1.8em;margin-bottom:1.1em}.analytics .detailed-row{padding-bottom:.8em}.analytics .detailed-row .row{font-size:1.2em}.analytics .detailed-row .row.header{font-size:.8em;color:#bab8b8;text-transform:uppercase}.field-title-row{padding-top:2em;padding-bottom:1em;border-top:#fafafa solid 1px;font-size:1.2em;color:#bab8b8}.field-detailed-row{font-size:1.2em;padding-bottom:.3em}.table-tools{border-top:#fafafa solid 1px;padding-top:2.5em}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:#000;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:#fff;background-color:rgba(256,256,256,.8)}.public-form.preview{border:none;box-shadow:0 0 10px 0 grey;overflow-y:scroll;overflow-x:hidden;height:400px;width:90%;position:absolute}.public-form input,.public-form textarea{background-color:#000;background-color:rgba(0,0,0,0);border-width:0}form .btn{border-color:grey}.public-form input.ng-untouched,.public-form input:focus,.public-form textarea.ng-untouched,.public-form textarea:focus{border-width:0 0 2px;border-color:rgba(246,255,181,.4);outline:0}.public-form input.ng-dirty,.public-form textarea.ng-dirty{border-width:0}.public-form input.empty,.public-form textarea.empty{border-width:0 0 2px;border-color:rgba(246,255,181,.4)}section.content p.breakwords{word-break:break-all}.public-form .btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}section.content>section>section.container{margin-top:70px}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px}.public-form .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;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-fields{position:relative;padding-top:10%}.public-form .letter{position:relative;display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;width:16px;padding:0;height:17px;font-size:12px;line-height:19px;border:1px solid #000;border:1px solid rgba(0,0,0,.2);margin-right:7px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-align:center;font-weight:700}div.form-submitted>.field.row{padding-bottom:2%;margin-top:10%}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 .field-number{margin-right:.5em}form .row.field{padding:1em 0 0;width:inherit}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:.5em;width:inherit}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:#000!important;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%}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%}form .required-error{color:#ddd;font-size:.8em}form .dropdown>.field-input input{min-height:34px;border-width:0 0 2px;border-radius:5px}form .dropdown>.field-input input:focus{border:none}form .dropdown>.field-input .ui-select-choices-row-inner{border-radius:3px;margin:5px;padding:10px;background-color:#000;background-color:rgba(0,0,0,.05)}form .dropdown>.field-input .ui-select-choices-row-inner.active,form .dropdown>.field-input .ui-select-choices-row-inner.active:focus{background-color:#000;background-color:rgba(0,0,0,.1)}.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%}.ui-select-choices.ui-select-dropdown{top:2.5em!important}.ui-select-toggle{box-shadow:none!important;border:none!important}section.public-form field-directive .btn.btn-lg.btn-default{background:0 0}section.public-form field-directive .btn[disabled]{display:none}.form-item{border-radius:5px;text-align:center;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.paused{background-color:red;color:#fff}.form-item.paused:hover{background-color:#8b0000;color:#fff}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#3FA2F7;color:#fff}.form-item.new-form{background-color:#ff8383;z-index:11}.form-item.new-form:hover{background-color:#3079b5}.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}.field-directive{opacity:.2;padding:2.5% 10%}.field-directive.activeField,.form-field-wrapper .form-actions.activeField{opacity:1}h3.forms-list-title{color:#3FA2F7;font-weight:600;margin-bottom:3em}.form-item{color:#71AADD;background-color:#E4F1FD}.form-item:hover{background-color:#3FA2F7;color:#23527C}.form-item.create-new:hover{color:#fff;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:1em}.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.create-new.new-button .details-row{padding-top:20%}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.form-item.create-new input{max-width:100%}section.auth{padding:70px 0;position:absolute;min-height:100%;top:0;left:0;width:100%;color:#fff;background-color:#50B5C1;background:-moz-linear-gradient(137deg,#50B5C1 0,#6450A0 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#50B5C1),color-stop(100%,#6450A0));background:-webkit-linear-gradient(137deg,#50B5C1 0,#6450A0 100%);background:-o-linear-gradient(137deg,#50B5C1 0,#6450A0 100%);background:-ms-linear-gradient(137deg,#50B5C1 0,#6450A0 100%)}section.auth>h3{font-size:2em;font-weight:500}.valign-wrapper{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.valign-wrapper .valign{display:block;width:100%}section.auth a{color:#fff;text-decoration:underline}section.auth.signup-view>h3{font-size:3em;padding-bottom:.5em}section.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;min-height:34px}section.auth input{color:#4c4c4c}section.auth .btn{border-radius:100px;font-size:14px;padding:12px 28px;margin-top:1em}.btn-rounded.btn-signup{background-color:#FFD747;color:#896D0B;border:2px solid #FFD747}.btn-rounded.btn-signup:hover{color:#FFD747;background-color:#896D0B;border:2px solid #896D0B}.btn-rounded.btn-default{background-color:transparent;color:#fff;border:2px solid #fff}.btn-rounded.btn-default:focus,.btn-rounded.btn-default:hover{color:#6450A0;background-color:#fff;border-color:#fff}@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 input.form-control{min-height:30px!important;border:none}input.form-control{height:auto;border-radius:4px;box-shadow:none;font-size:18px;padding:20px 10px} \ No newline at end of file diff --git a/public/dist/form_populate_template_cache.js b/public/dist/form_populate_template_cache.js new file mode 100644 index 00000000..e9c798fb --- /dev/null +++ b/public/dist/form_populate_template_cache.js @@ -0,0 +1,35 @@ +angular.module('TellForm-Form.form_templates', []).run(['$templateCache', function ($templateCache) { + "use strict"; + $templateCache.put("form_modules/forms/base/views/form-not-found.client.view.html", + "

{{ 'FORM_404_HEADER' | translate }}

{{ 'FORM_404_BODY' | translate }}
"); + $templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html", + "

{{ 'FORM_UNAUTHORIZED_HEADER' | translate }}

{{ 'FORM_UNAUTHORIZED_BODY1' | translate }}
{{ 'FORM_UNAUTHORIZED_BODY2' | translate }}
"); + $templateCache.put("form_modules/forms/base/views/submit-form.client.view.html", + "
"); + $templateCache.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html", + "

{{pageData.introTitle}}

{{pageData.introParagraph}}

"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/date.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}

"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/dropdown.html", + "
0\">

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/hidden.html", + ""); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/legal.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}


{{field.description}}


"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/radio.html", + "
0\">

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/rating.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}

"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/statement.html", + "

{{field.title}}

{{field.description}}

{{field.description}}


"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/textarea.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{ 'NEWLINE' | translate }}

{{field.description}}

{{ 'ADD_NEW_LINE_INSTR' | translate }}
{{ 'ENTER' | translate }}
"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/textfield.html", + "

{{index+1}} {{field.title}} ({{ 'OPTIONAL' | translate }})

{{field.description}}

{{ 'ENTER' | translate }}
"); + $templateCache.put("form_modules/forms/base/views/directiveViews/field/yes_no.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


"); + $templateCache.put("form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html", + "
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
{{ 'ENTER' | translate }}

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

"); +}]); diff --git a/public/form_modules/forms/base/css/form.css b/public/form_modules/forms/base/css/form.css index 2a9665bd..f8dbfdf6 100644 --- a/public/form_modules/forms/base/css/form.css +++ b/public/form_modules/forms/base/css/form.css @@ -372,7 +372,6 @@ div.config-form .row.field { background-color:#efefef; } - /*Styles for add fields tab*/ .admin-form .add-field { background-color: #ddd; @@ -389,10 +388,6 @@ 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/form_modules/forms/base/directives/submit-form.client.directive.js b/public/form_modules/forms/base/directives/submit-form.client.directive.js index 3798eb40..53b9005a 100644 --- a/public/form_modules/forms/base/directives/submit-form.client.directive.js +++ b/public/form_modules/forms/base/directives/submit-form.client.directive.js @@ -285,8 +285,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun }; $rootScope.prevField = $scope.prevField = function(){ - console.log('prevField'); - console.log($scope.selected); var selected_index = $scope.selected.index - 1; if($scope.selected.index > 0){ $scope.setActiveField(null, selected_index, true); @@ -380,17 +378,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun if($scope.myform.form_fields[i].fieldType === 'dropdown' && !$scope.myform.form_fields[i].deletePreserved){ $scope.myform.form_fields[i].fieldValue = $scope.myform.form_fields[i].fieldValue.option_value; } - - //Get rid of unnessecary attributes for each form field - delete form.form_fields[i].submissionId; - delete form.form_fields[i].disabled; - delete form.form_fields[i].ratingOptions; - delete form.form_fields[i].fieldOptions; - delete form.form_fields[i].logicJump; - delete form.form_fields[i].description; - delete form.form_fields[i].validFieldTypes; - delete form.form_fields[i].fieldType; - } setTimeout(function () { diff --git a/public/form_modules/forms/base/views/directiveViews/field/dropdown.html b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html index 64d2863c..b3ac8087 100755 --- a/public/form_modules/forms/base/views/directiveViews/field/dropdown.html +++ b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html @@ -15,11 +15,10 @@
>>>>>> 2.20 //Redirect to listForms if user is authenticated if(statesToIgnore.indexOf(toState.name) > 0){ if(Auth.isAuthenticated()){ diff --git a/public/modules/forms/admin/config/i18n/english.js b/public/modules/forms/admin/config/i18n/english.js index 3759d236..bdaa3b46 100644 --- a/public/modules/forms/admin/config/i18n/english.js +++ b/public/modules/forms/admin/config/i18n/english.js @@ -6,16 +6,30 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid //Configure Form Tab View ADVANCED_SETTINGS: 'Advanced Settings', - FORM_NAME: 'Form Name', - FORM_STATUS: 'Form Status', + FORM_NAME: 'Your tellform is called', + FORM_STATUS: 'Status', PUBLIC: 'Public', PRIVATE: 'Private', GA_TRACKING_CODE: 'Google Analytics Tracking Code', - DISPLAY_FOOTER: 'Display Form Footer?', + DISPLAY_FOOTER: 'Form Footer', SAVE_CHANGES: 'Save Changes', CANCEL: 'Cancel', - DISPLAY_START_PAGE: 'Display Start Page?', - DISPLAY_END_PAGE: 'Display Custom End Page?', + DISPLAY_START_PAGE: 'Start Page', + DISPLAY_END_PAGE: 'Custom End Page', + GENERAL_TAB: 'General', + SELF_NOTIFICATIONS_TAB: 'Self notifications', + RESPONDENT_NOTIFICATIONS_TAB: 'Respondent notifications', + + SEND_NOTIFICATION_TO: 'Send to', + NO_EMAIL_FIELD_WARNING: 'Error: You need an email field in your form to send the email to your form respondent', + REPLY_TO: 'Reply to', + EMAIL_SUBJECT: 'Subject', + EMAIL_MESSAGE: 'Message', + ENABLE_RESPONDENT_NOTIFICATIONS: 'Respondent Notifications are currently', + ENABLE_SELF_NOTIFICATIONS: 'Self Notifications are currently', + TOGGLE_ENABLED: 'Enabled', + TOGGLE_DISABLED: 'Disabled', + ADD_VARIABLE_BUTTON: 'Add variable', //List Forms View CREATE_A_NEW_FORM: 'Create a new form', @@ -47,7 +61,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid DELETE_FORM_MD: 'Delete Form', DELETE: 'Delete', FORM: 'Form', - VIEW: 'View', + VIEW_MY_TELLFORM: 'View my tellform', LIVE: 'Live', PREVIEW: 'Preview', COPY: 'Copy', diff --git a/public/modules/forms/admin/config/i18n/french.js b/public/modules/forms/admin/config/i18n/french.js index d9675934..5cee1263 100644 --- a/public/modules/forms/admin/config/i18n/french.js +++ b/public/modules/forms/admin/config/i18n/french.js @@ -5,16 +5,31 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid $translateProvider.translations('fr', { // Configurer la vue de l'onglet Formulaire ADVANCED_SETTINGS: 'Paramètres avancés', - FORM_NAME: "Nom du formulaire", - FORM_STATUS: 'Statut du formulaire', + FORM_NAME: "Votre tellform est appelé", + FORM_STATUS: 'Statut', PUBLIC: 'Public', PRIVATE: "Privé", GA_TRACKING_CODE: "Code de suivi Google Analytics", - DISPLAY_FOOTER: "Afficher le pied de formulaire?", + DISPLAY_FOOTER: "Pied de formulaire", SAVE_CHANGES: 'Enregistrer les modifications', CANCEL: 'Annuler', - DISPLAY_START_PAGE: "Afficher la page de démarrage?", - DISPLAY_END_PAGE: "Afficher la page de fin personnalisée?", + DISPLAY_START_PAGE: "Page de démarrage", + DISPLAY_END_PAGE: "Page de fin personnalisée", + + GENERAL_TAB: 'General', + SELF_NOTIFICATIONS_TAB: 'Self notifications', + RESPONDANT_NOTIFICATIONS_TAB: 'Respondent notifications', + + SEND_NOTIFICATION_TO: 'Envoyer à', + NO_EMAIL_FIELD_WARNING: 'Erreur: Vous avez besoin d\'un champ e-mail dans votre formulaire pour envoyer l\'e-mail au répondant de votre formulaire', + REPLY_TO: "Répondre à", + EMAIL_SUBJECT: 'Sujet', + EMAIL_MESSAGE: "Message", + ENABLE_RESPONDENT_NOTIFICATIONS: 'Les notifications des répondants sont actuellement', + ENABLE_SELF_NOTIFICATIONS: 'Les notifications automatiques sont actuellement', + TOGGLE_ENABLED: 'Activé', + TOGGLE_DISABLED: 'Désactivé', + ADD_VARIABLE_BUTTON: "Ajouter une variable", // Afficher les formulaires CREATE_A_NEW_FORM: "Créer un nouveau formulaire", @@ -46,7 +61,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid DELETE_FORM_MD: "Supprimer le formulaire", DELETE: "Supprimer", FORM: 'Formulaire', - VIEW: "Afficher", + VIEW_MY_TELLFORM: "Afficher ma forme", LIVE: "Live", PREVIEW: 'Aperçu', COPY: "Copier", diff --git a/public/modules/forms/admin/config/i18n/german.js b/public/modules/forms/admin/config/i18n/german.js index fa3dd2b3..bea90bd3 100644 --- a/public/modules/forms/admin/config/i18n/german.js +++ b/public/modules/forms/admin/config/i18n/german.js @@ -5,16 +5,31 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid $translateProvider.translations('de', { // Konfigurieren der Formularregisterkarte ADVANCED_SETTINGS: 'Erweiterte Einstellungen', - FORM_NAME: 'Formularname', - FORM_STATUS: 'Formularstatus', + FORM_NAME: 'Ihr tellform heißt', + FORM_STATUS: 'Status', PUBLIC: 'Öffentlich', PRIVATE: 'Privat', GA_TRACKING_CODE: 'Google Analytics Tracking-Code', - DISPLAY_FOOTER: 'Formularfußzeile anzeigen?', + DISPLAY_FOOTER: 'Fußzeile', SAVE_CHANGES: 'Änderungen speichern', CANCEL: 'Abbrechen', - DISPLAY_START_PAGE: 'Startseite anzeigen?', - DISPLAY_END_PAGE: 'Benutzerdefinierte Endseite anzeigen?', + DISPLAY_START_PAGE: 'Startseite', + DISPLAY_END_PAGE: 'Benutzerdefinierte Endseite', + + GENERAL_TAB: 'Allgemein', + SELF_NOTIFICATIONS_TAB: 'Selbstbenachrichtigungen', + RESPONDANT_NOTIFICATIONS_TAB: 'Beantwortungsbenachrichtigungen', + + SEND_NOTIFICATION_TO: 'Senden an', + NO_EMAIL_FIELD_WARNING: 'Fehler: Sie benötigen ein E-Mail-Feld in Ihrem Formular, um die E-Mail an Ihr Formular zu senden.', + REPLY_TO: 'Antworten auf', + EMAIL_SUBJECT: "Betreff", + EMAIL_MESSAGE: 'Nachricht', + ENABLE_RESPONDENT_NOTIFICATIONS: 'Antwortbenachrichtigungen sind derzeit', + ENABLE_SELF_NOTIFICATIONS: 'Selbstbenachrichtigungen sind derzeit', + TOGGLE_ENABLED: 'Aktiviert', + TOGGLE_DISABLED: 'Deaktiviert', + ADD_VARIABLE_BUTTON: 'Variable hinzufügen', // Listenformularansicht CREATE_A_NEW_FORM: 'Erstelle ein neues Formular', @@ -46,7 +61,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid DELETE_FORM_MD: 'Formular löschen', DELETE: 'Löschen', FORM: 'Formular', - VIEW: 'Ansicht', + VIEW_MY_TELLFORM: 'Mein tellform anzeigen', LIVE: 'Leben', PREVIEW: 'Vorschau', COPY: 'Kopieren', diff --git a/public/modules/forms/admin/config/i18n/italian.js b/public/modules/forms/admin/config/i18n/italian.js index 1414e891..f1695356 100644 --- a/public/modules/forms/admin/config/i18n/italian.js +++ b/public/modules/forms/admin/config/i18n/italian.js @@ -5,16 +5,31 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid $translateProvider.translations('it', { // Configura la visualizzazione scheda modulo ADVANCED_SETTINGS: 'Impostazioni avanzate', - FORM_NAME: 'Nome modulo', - FORM_STATUS: 'Stato modulo', + FORM_NAME: 'Il tuo tellform è chiamato', + FORM_STATUS: 'Stato', PUBLIC: 'pubblico', PRIVATE: 'Privato', GA_TRACKING_CODE: 'Codice di monitoraggio di Google Analytics', - DISPLAY_FOOTER: 'Visualizza piè di pagina?', + DISPLAY_FOOTER: 'Piè di pagina', SAVE_CHANGES: 'Salva modifiche', CANCEL: 'Annulla', - DISPLAY_START_PAGE: 'Visualizza pagina iniziale?', - DISPLAY_END_PAGE: 'Mostra pagina finale personalizzata?', + DISPLAY_START_PAGE: 'Pagina iniziale', + DISPLAY_END_PAGE: 'Pagina finale personalizzata', + + GENERAL_TAB: 'Generale', + SELF_NOTIFICATIONS_TAB: 'Autodiagnosi', + RESPONDANT_NOTIFICATIONS_TAB: 'Notifiche rispondenti', + + SEND_NOTIFICATION_TO: 'Invia a', + NO_EMAIL_FIELD_WARNING: 'Errore: Hai bisogno di un campo e-mail nel tuo modulo per inviare l\'email al tuo interlocutore', + REPLY_TO: 'Rispondi a', + EMAIL_SUBJECT: 'Oggetto', + EMAIL_MESSAGE: 'Messaggio', + ENABLE_RESPONDENT_NOTIFICATIONS: 'Notifiche rispondenti sono attualmente', + ENABLE_SELF_NOTIFICATIONS: 'Le notifiche auto sono attualmente', + TOGGLE_ENABLED: 'Abilitato', + TOGGLE_DISABLED: 'disabilitato', + ADD_VARIABLE_BUTTON: 'Aggiungi variabile', // Visualizzazione dei moduli di elenco CREATE_A_NEW_FORM: 'Crea un nuovo modulo', @@ -46,7 +61,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid DELETE_FORM_MD: 'Elimina modulo', DELETE: 'Elimina', FORM: 'Forma', - VIEW: 'Visualizza', + VIEW_MY_TELLFORM: 'Visualizza la mia informazione', LIVE: 'Live', PREVIEW: 'Anteprima', COPY: 'Copia', diff --git a/public/modules/forms/admin/config/i18n/spanish.js b/public/modules/forms/admin/config/i18n/spanish.js index 26c7199d..c61d8e25 100644 --- a/public/modules/forms/admin/config/i18n/spanish.js +++ b/public/modules/forms/admin/config/i18n/spanish.js @@ -3,19 +3,33 @@ angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('es', { - //Configure Form Tab View ADVANCED_SETTINGS: 'Configuraciones avanzadas', - FORM_NAME: 'Nombre del formulario', - FORM_STATUS: 'Estado del formulario', + FORM_NAME: 'Tu tellform se llama', + FORM_STATUS: 'Estado', PUBLIC: 'Público', PRIVATE: 'Privado', GA_TRACKING_CODE: 'Código de Google Analytics', - DISPLAY_FOOTER: '¿Mostrar pie de página?', + DISPLAY_FOOTER: 'Pie de página', SAVE_CHANGES: 'Grabar', CANCEL: 'Cancelar', - DISPLAY_START_PAGE: '¿Mostrar página de inicio?', - DISPLAY_END_PAGE: '¿Mostrar paǵina de fin?', + DISPLAY_START_PAGE: 'Página de inicio', + DISPLAY_END_PAGE: 'Página final personalizada', + + SELF_NOTIFICATIONS_TAB: 'Auto notificaciones', + RESPONDANT_NOTIFICATIONS_TAB: 'Notificaciones de los demandados', + GENERAL_TAB: 'Général', + + SEND_NOTIFICATION_TO: 'Enviar a', + NO_EMAIL_FIELD_WARNING: 'Error: necesita un campo de correo electrónico en su formulario para enviar el correo electrónico a su encuestado', + REPLY_TO: 'Responder a', + EMAIL_SUBJECT: 'Asunto', + EMAIL_MESSAGE: 'Mensaje', + ENABLE_RESPONDENT_NOTIFICATIONS: 'Las notificaciones de los demandados son actualmente', + ENABLE_SELF_NOTIFICATIONS: 'Las notificaciones automáticas están actualmente', + TOGGLE_ENABLED: 'Habilitado', + TOGGLE_DISABLED: 'Desactivado', + ADD_VARIABLE_BUTTON: 'Agregar variable', //List Forms View CREATE_A_NEW_FORM: 'Crear formulario', @@ -47,7 +61,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid DELETE_FORM_MD: 'Borrar formulario', DELETE: 'Borrar', FORM: 'Formulario', - VIEW: 'Vista', + VIEW_MY_TELLFORM: 'Ver mi tellform', LIVE: 'Online', PREVIEW: 'Vista previa', COPY: 'Copiar', diff --git a/public/modules/forms/admin/controllers/admin-form.client.controller.js b/public/modules/forms/admin/controllers/admin-form.client.controller.js index 12c85f3c..7326426a 100644 --- a/public/modules/forms/admin/controllers/admin-form.client.controller.js +++ b/public/modules/forms/admin/controllers/admin-form.client.controller.js @@ -4,19 +4,12 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$window', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', '$filter', '$translate', function($rootScope, $window, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm, $filter, $translate) { - //Set active tab to Create - $scope.activePill = 0; - - $scope.copied = false; - $scope.onCopySuccess = function (e) { - $scope.copied = true; - }; - $scope = $rootScope; $scope.animationsEnabled = true; $scope.myform = myForm; $rootScope.saveInProgress = false; $scope.oldForm = _.cloneDeep($scope.myform); + $scope.designTabActive = false CurrentForm.setForm($scope.myform); @@ -36,7 +29,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo $scope.actualFormURL = window.location.protocol + '//' + window.location.host + $scope.formURL; } - var refreshFrame = $scope.refreshFrame = function(){ if(document.getElementById('iframe')) { document.getElementById('iframe').contentWindow.location.reload(); @@ -44,13 +36,59 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo }; $scope.tabData = [ + { + heading: $filter('translate')('CREATE_TAB'), + route: 'viewForm.create', + active: false + }, { heading: $filter('translate')('CONFIGURE_TAB'), - templateName: 'configure' + route: 'viewForm.configure.general', + active: false + }, + { + heading: $filter('translate')('ANALYZE_TAB'), + route: 'viewForm.analyze', + active: false + }, + { + heading: $filter('translate')('SHARE_TAB'), + route: 'viewForm.share', + active: false + }, + { + heading: $filter('translate')('DESIGN_TAB'), + route: 'viewForm.design', + active: false } ]; - $scope.designTabActive = false + $scope.go = function(tab){ + var currParentState = $state.current.name.split('.').slice(0,2).join('.'); + var tabParentState = tab.route.split('.').slice(0,2).join('.'); + + if(currParentState !== tabParentState && tabParentState !== 'viewForm.configure.general'){ + $state.go(tab.route); + } + }; + + function setActiveTab() { + $scope.tabData.forEach(function(tab) { + var currentTabState = $state.current.name.split('.').slice(0,2).join('.'); + var tabRouteState = tab.route.split('.').slice(0,2).join('.'); + tab.active = (currentTabState === tabRouteState); + + if(tab.active && tab.route === 'viewForm.design'){ + $scope.designTabActive = true; + } else { + $scope.designTabActive = false; + } + }); + } + + setActiveTab(); + + $scope.$on("$stateChangeSuccess", setActiveTab()); $scope.deactivateDesignTab = function(){ $scope.designTabActive = false diff --git a/public/modules/forms/admin/css/edit-form-configure.css b/public/modules/forms/admin/css/edit-form-configure.css new file mode 100644 index 00000000..afe5b2b2 --- /dev/null +++ b/public/modules/forms/admin/css/edit-form-configure.css @@ -0,0 +1,43 @@ +.tag { + background-color: #999; + border-radius: 3px 3px 3px 3px; + border: 0; + color: #FFFFFF; + font-style: inherit; + font-size: 11px; + padding: 4px 5px; + margin: 0 2px 2px 2px; + font-family: inherit; + white-space: nowrap; + vertical-align: middle; + cursor: pointer !important; + pointer-events: none; +} + +.email-subject.ta-root .ta-editor.ta-html, .email-subject .ta-scroll-window.form-control { + min-height: 0; + overflow: hidden; + height: auto; + border-radius: 4px; + box-shadow: none; + font-size: 18px; + padding-top: 10px; +} + +.email-subject.ta-root .ta-scroll-window > .ta-bind { + min-height: 0; + outline: 0; +} + +.ui-select input.form-control { + height: 34px; + padding: 6px; +} + +.config-form .btn-secondary { + border-color: #DDDDDD; +} + +.notification-toggle.toggle-switch { + margin: 5px 0; +} \ No newline at end of file diff --git a/public/modules/forms/admin/css/edit-form.css b/public/modules/forms/admin/css/edit-form.css index 4d8923ae..3ac8a10a 100644 --- a/public/modules/forms/admin/css/edit-form.css +++ b/public/modules/forms/admin/css/edit-form.css @@ -247,9 +247,25 @@ div.config-form .row.field { margin: 10px 0 10px; } +.view-form-btn { + border: none; +} .view-form-btn.span { padding-right:0.6em; } + +.notification-row { + display: inline-block; + padding: 0 5px; +} + +.status-light { + font-size: 10px; +} + +.notification-row .status-light { + padding-top: 15px; +} .status-light.status-light-off { color: #BE0000; } diff --git a/public/modules/forms/admin/directives/configure-form.client.directive.js b/public/modules/forms/admin/directives/configure-form.client.directive.js index fe60f778..a1caa7c5 100644 --- a/public/modules/forms/admin/directives/configure-form.client.directive.js +++ b/public/modules/forms/admin/directives/configure-form.client.directive.js @@ -1,23 +1,79 @@ 'use strict'; -angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', 'CurrentForm', - function ($rootScope, $http, Upload, CurrentForm) { +angular.module('forms').directive('configureFormDirective', ['$rootScope', '$filter', '$state', + function ($rootScope, $filter, $state) { return { templateUrl: 'modules/forms/admin/views/directiveViews/form/configure-form.client.view.html', restrict: 'E', scope: { - myform:'=', - user:'=', - pdfFields:'@', - formFields:'@' + myform:'=' }, controller: function($scope){ - $scope.log = ''; + $rootScope.myform = $scope.myform; $scope.languages = $rootScope.languages; - $scope.resetForm = $rootScope.resetForm; $scope.update = $rootScope.update; + $scope.$evalAsync(function() { + angular.element('.tag') + }); + + $scope.languages = ['en', 'fr', 'es', 'it', 'de']; + + $scope.langCodeToWord = { + 'en': 'English', + 'fr': 'Français', + 'es': 'Español', + 'it': 'Italiàno', + 'de': 'Deutsch' + }; + + $scope.wordToLangCode = { + 'English': 'en', + 'Français': 'fr', + 'Español': 'es', + 'Italiàno': 'it', + 'Deutsch': 'de' + }; + + $scope.configureTabs = [ + { + heading: $filter('translate')('GENERAL_TAB'), + route: 'viewForm.configure.general', + active: false + }, + { + heading: $filter('translate')('SELF_NOTIFICATIONS_TAB'), + route: 'viewForm.configure.self_notifications', + active: false + }, + { + heading: $filter('translate')('RESPONDENT_NOTIFICATIONS_TAB'), + route: 'viewForm.configure.respondent_notifications', + active: false + } + ]; + + $scope.emailFields = $scope.myform.form_fields.filter(function(field){ + return field.fieldType === 'email'; + }); + + $scope.formHasEmailField = ($scope.emailFields.length > 0); + + $scope.go = function(tab){ + tab.active = true; + $state.go(tab.route); + }; + + function setActiveTab() { + $scope.configureTabs.forEach(function(tab) { + tab.active = ($state.current.name === tab.route); + }); + } + + setActiveTab(); + + $scope.$on("$stateChangeSuccess", setActiveTab()); } }; } diff --git a/public/modules/forms/admin/directives/design-form.client.directive.js b/public/modules/forms/admin/directives/design-form.client.directive.js new file mode 100644 index 00000000..d786c91e --- /dev/null +++ b/public/modules/forms/admin/directives/design-form.client.directive.js @@ -0,0 +1,14 @@ +'use strict'; + +angular.module('forms').directive('designFormDirective', [ + function () { + return { + templateUrl: 'modules/forms/admin/views/directiveViews/form/design-form.client.view.html', + restrict: 'E', + scope: { + myform:'=', + formurl: '=' + } + } + } +]); \ No newline at end of file diff --git a/public/modules/forms/admin/directives/edit-form.client.directive.js b/public/modules/forms/admin/directives/edit-form.client.directive.js index 28cd0d6b..79f39e48 100644 --- a/public/modules/forms/admin/directives/edit-form.client.directive.js +++ b/public/modules/forms/admin/directives/edit-form.client.directive.js @@ -1,4 +1,3 @@ - 'use strict'; angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormFields', '$uibModal', diff --git a/public/modules/forms/admin/directives/share-form.client.directive.js b/public/modules/forms/admin/directives/share-form.client.directive.js new file mode 100644 index 00000000..ad8d1536 --- /dev/null +++ b/public/modules/forms/admin/directives/share-form.client.directive.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('forms').directive('shareFormDirective', ['$rootScope', + function ($rootScope) { + return { + templateUrl: 'modules/forms/admin/views/directiveViews/form/share-form.client.view.html', + restrict: 'E', + scope: { + actualformurl:'=' + }, + controller: function($scope){ + $scope.actualFormURL = $scope.actualformurl; + } + }; + } +]); \ No newline at end of file diff --git a/public/modules/forms/admin/services/form-fields.client.service.js b/public/modules/forms/admin/services/form-fields.client.service.js index 302603ae..be6ff3c9 100644 --- a/public/modules/forms/admin/services/form-fields.client.service.js +++ b/public/modules/forms/admin/services/form-fields.client.service.js @@ -1,11 +1,18 @@ 'use strict'; //TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server +<<<<<<< HEAD +angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$window', + function($rootScope, $translate, $window) { + console.log($window.user); + $translate.use($window.user.language); +======= angular.module('forms').service('FormFields', [ '$rootScope', '$translate', 'Auth', function($rootScope, $translate, Auth) { var language = Auth.ensureHasCurrentUser().language; $translate.use(language); +>>>>>>> 2.20 this.types = [ { diff --git a/public/modules/forms/admin/views/admin-form.client.view.html b/public/modules/forms/admin/views/admin-form.client.view.html index bbcc183b..9d922ee1 100644 --- a/public/modules/forms/admin/views/admin-form.client.view.html +++ b/public/modules/forms/admin/views/admin-form.client.view.html @@ -42,158 +42,26 @@
-
- - - - - -
-
- - - - -
-
-
- - -
-
- {{ 'TELLFORM_URL' | translate }} -
-
- -
-
- -
-
-
- -
-
- {{ 'COPY_AND_PASTE' | translate }} -
-
- - - -
-
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
{{ 'BACKGROUND_COLOR' | translate }}
-
-
- -
-
- -
-
-
{{ 'QUESTION_TEXT_COLOR' | translate }}
-
- -
- -
-
- -
-
-
{{ 'ANSWER_TEXT_COLOR' | translate }}
-
- -
- -
-
- -
-
-
{{ 'BTN_BACKGROUND_COLOR' | translate }}
-
- -
- -
-
-
-
-
{{ 'BTN_TEXT_COLOR' | translate }}
-
- -
- -
-
-
- -
- -
-
- -
-
- -
-
-
+
+ +
+
+
+
diff --git a/public/modules/forms/admin/views/adminTabs/configure.html b/public/modules/forms/admin/views/adminTabs/configure.html index f4a971ff..e8b52e02 100644 --- a/public/modules/forms/admin/views/adminTabs/configure.html +++ b/public/modules/forms/admin/views/adminTabs/configure.html @@ -1,2 +1,4 @@ + + \ No newline at end of file diff --git a/public/modules/forms/admin/views/adminTabs/configureTabs/general.html b/public/modules/forms/admin/views/adminTabs/configureTabs/general.html new file mode 100644 index 00000000..2815e6f3 --- /dev/null +++ b/public/modules/forms/admin/views/adminTabs/configureTabs/general.html @@ -0,0 +1,106 @@ + +
+
+
+
+

{{ 'FORM_NAME' | translate }}

+
+ +
+ +
+
+ +
+

{{ 'LANGUAGE' | translate }}

+
+ + + {{ langCodeToWord[$select.selected] }} + + + + + + + * {{ 'REQUIRED_FIELD' | translate }} +
+
+ +
+
+

{{ 'FORM_STATUS' | translate }}

+
+ +
+ +
+
+ +
+
+

{{ 'GA_TRACKING_CODE' | translate }}

+
+ +
+ +
+
+
+
+

{{ 'DISPLAY_FOOTER' | translate }}

+
+ +
+ +
+
+ +
+
+

{{ 'DISPLAY_START_PAGE' | translate }}

+
+ +
+ +
+
+ +
+
+

{{ 'DISPLAY_END_PAGE' | translate }}

+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/public/modules/forms/admin/views/adminTabs/configureTabs/respondent-notifications.html b/public/modules/forms/admin/views/adminTabs/configureTabs/respondent-notifications.html new file mode 100644 index 00000000..a15da9ce --- /dev/null +++ b/public/modules/forms/admin/views/adminTabs/configureTabs/respondent-notifications.html @@ -0,0 +1,81 @@ +
+
+
+
+ + +
+
+
{{ 'ENABLE_RESPONDENT_NOTIFICATIONS' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'SEND_NOTIFICATION_TO' | translate }}:
+
+ +
+ + + {{$select.selected.title}} + + + + + + +
+
+ +
+ + {{ 'NO_EMAIL_FIELD_WARNING' | translate }} + +
+ +
+
+
{{ 'REPLY_TO' | translate }}:
+
+ +
+ +
+
+ +
+
+
{{ 'EMAIL_SUBJECT' | translate }}:
+
+
+ +
+
+ +
+
+
{{ 'EMAIL_MESSAGE' | translate }}
+
+ +
+ +
+
+
+
+
\ No newline at end of file diff --git a/public/modules/forms/admin/views/adminTabs/configureTabs/self-notifications.html b/public/modules/forms/admin/views/adminTabs/configureTabs/self-notifications.html new file mode 100644 index 00000000..adc03dbd --- /dev/null +++ b/public/modules/forms/admin/views/adminTabs/configureTabs/self-notifications.html @@ -0,0 +1,74 @@ +
+
+ +
+
+ + +
+ +
+
{{ 'ENABLE_SELF_NOTIFICATIONS' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'SEND_NOTIFICATION_TO' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'REPLY_TO' | translate }}
+
+ +
+ + + {{$select.selected.title}} + + + + + + +
+
+ +
+
+
{{ 'EMAIL_SUBJECT' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'EMAIL_MESSAGE' | translate }}
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/public/modules/forms/admin/views/adminTabs/design.html b/public/modules/forms/admin/views/adminTabs/design.html new file mode 100644 index 00000000..06a465bf --- /dev/null +++ b/public/modules/forms/admin/views/adminTabs/design.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/modules/forms/admin/views/adminTabs/share.html b/public/modules/forms/admin/views/adminTabs/share.html new file mode 100644 index 00000000..5e005983 --- /dev/null +++ b/public/modules/forms/admin/views/adminTabs/share.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/modules/forms/admin/views/directiveViews/form/configure-form.client.view.html b/public/modules/forms/admin/views/directiveViews/form/configure-form.client.view.html index 67397b66..1120e475 100644 --- a/public/modules/forms/admin/views/directiveViews/form/configure-form.client.view.html +++ b/public/modules/forms/admin/views/directiveViews/form/configure-form.client.view.html @@ -1,133 +1,13 @@
- +
-
-
-
-
{{ 'FORM_NAME' | translate }}
-
+ + +
+
+
+
-
- -
-
- -
-
-
{{ 'FORM_STATUS' | translate }}
-
- -
- - - - - -
-
- -
-
{{ 'LANGUAGE' | translate }}
-
- - * {{ 'REQUIRED_FIELD' | translate }} -
-
-
-
-
-
-
{{ 'GA_TRACKING_CODE' | translate }}
-
- -
- -
-
-
-
-
{{ 'DISPLAY_FOOTER' | translate }}
-
- -
- - - -
-
- -
-
-
{{ 'DISPLAY_START_PAGE' | translate }}
-
- -
- - - - - -
-
- -
-
-
{{ 'DISPLAY_END_PAGE' | translate }}
-
- -
- - - - - -
-
-
-
diff --git a/public/modules/forms/admin/views/directiveViews/form/design-form.client.view.html b/public/modules/forms/admin/views/directiveViews/form/design-form.client.view.html new file mode 100644 index 00000000..8c0783c0 --- /dev/null +++ b/public/modules/forms/admin/views/directiveViews/form/design-form.client.view.html @@ -0,0 +1,76 @@ +
+
+
+
+
+
{{ 'BACKGROUND_COLOR' | translate }}
+
+
+ +
+
+ +
+
+
{{ 'QUESTION_TEXT_COLOR' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'ANSWER_TEXT_COLOR' | translate }}
+
+ +
+ +
+
+ +
+
+
{{ 'BTN_BACKGROUND_COLOR' | translate }}
+
+ +
+ +
+
+
+
+
{{ 'BTN_TEXT_COLOR' | translate }}
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
\ No newline at end of file diff --git a/public/modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html b/public/modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html index 4f7f0889..0b8b67b8 100644 --- a/public/modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html +++ b/public/modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html @@ -1,4 +1,4 @@ -
+
diff --git a/public/modules/forms/admin/views/directiveViews/form/share-form.client.view.html b/public/modules/forms/admin/views/directiveViews/form/share-form.client.view.html new file mode 100644 index 00000000..cc795b54 --- /dev/null +++ b/public/modules/forms/admin/views/directiveViews/form/share-form.client.view.html @@ -0,0 +1,44 @@ +
+
+
+ + +
+
+ {{ 'TELLFORM_URL' | translate }} +
+
+ +
+
+ +
+
+
+ +
+
+ {{ 'COPY_AND_PASTE' | translate }} +
+
+ + + +
+
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/public/modules/forms/base/css/form.css b/public/modules/forms/base/css/form.css index 03537d98..a3e97b4e 100644 --- a/public/modules/forms/base/css/form.css +++ b/public/modules/forms/base/css/form.css @@ -224,13 +224,13 @@ form .row.field { font-size:0.8em; } - form .row.field.dropdown > .field-input input { + form .dropdown > .field-input input { min-height: 34px; border-width: 0 0 2px 0; border-radius: 5px; } - form .row.field.dropdown > .field-input input:focus { + form .dropdown > .field-input input:focus { border: none; } diff --git a/public/modules/forms/config/forms.client.config.js b/public/modules/forms/config/forms.client.config.js index dec0f715..bbf01063 100644 --- a/public/modules/forms/config/forms.client.config.js +++ b/public/modules/forms/config/forms.client.config.js @@ -6,6 +6,15 @@ angular.module('forms').run(['Menus', // Set top bar menu items Menus.addMenuItem('topbar', 'My Forms', 'forms', '', '/forms', false); } +]).run(['$rootScope', '$state', + function($rootScope, $state) { + $rootScope.$on('$stateChangeStart', function(evt, to, params) { + if (to.redirectTo) { + evt.preventDefault(); + $state.go(to.redirectTo, params) + } + }); + } ]).filter('secondsToDateTime', [function() { return function(seconds) { return new Date(1970, 0, 1).setSeconds(seconds); @@ -46,4 +55,31 @@ angular.module('forms').run(['Menus', directive.replace = true; return $delegate; }); -}]); +}]).config(['$provide', function ($provide){ + $provide.decorator('taOptions', ['$delegate', 'taRegisterTool', '$translate', '$window', function(taOptions, taRegisterTool, $translate, $window) { + taRegisterTool('insertField', { + display: '', + onClickField: function(field_id, field_name){ + this.$editor().wrapSelection('insertHTML', '' + field_name + '', false); + }, + action: function(){ + } + }); + + taOptions.defaultTagAttributes['var'] = { + 'contenteditable': 'false' + }; + + return taOptions; + }]); +}]); \ 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 aa38bde0..a01d4d91 100644 --- a/public/modules/forms/config/forms.client.routes.js +++ b/public/modules/forms/config/forms.client.routes.js @@ -43,6 +43,7 @@ angular.module('forms').config(['$stateProvider', controller: 'SubmitFormController', controllerAs: 'ctrl' }).state('viewForm', { + abstract: true, url: '/forms/:formId/admin', templateUrl: 'modules/forms/admin/views/admin-form.client.view.html', data: { @@ -63,18 +64,35 @@ angular.module('forms').config(['$stateProvider', }] }, controller: 'AdminFormController' - }).state('viewForm.configure', { + }).state('viewForm.create', { + url: '/create', + templateUrl: 'modules/forms/admin/views/adminTabs/create.html' + }) + + .state('viewForm.configure', { + abstract: true, url: '/configure', templateUrl: 'modules/forms/admin/views/adminTabs/configure.html' - }).state('viewForm.design', { + }).state('viewForm.configure.general', { + url: '/general', + templateUrl: 'modules/forms/admin/views/adminTabs/configureTabs/general.html' + }).state('viewForm.configure.self_notifications', { + url: '/self_notifications', + templateUrl: 'modules/forms/admin/views/adminTabs/configureTabs/self-notifications.html' + }).state('viewForm.configure.respondent_notifications', { + url: '/respondent_notifications', + templateUrl: 'modules/forms/admin/views/adminTabs/configureTabs/respondent-notifications.html' + }) + + .state('viewForm.design', { url: '/design', templateUrl: 'modules/forms/admin/views/adminTabs/design.html' + }).state('viewForm.share', { + url: '/share', + templateUrl: 'modules/forms/admin/views/adminTabs/share.html' }).state('viewForm.analyze', { url: '/analyze', templateUrl: 'modules/forms/admin/views/adminTabs/analyze.html' - }).state('viewForm.create', { - url: '/create', - templateUrl: 'modules/forms/admin/views/adminTabs/create.html' }); } ]); diff --git a/public/modules/forms/forms.client.module.js b/public/modules/forms/forms.client.module.js index 07d98366..1c7fb122 100644 --- a/public/modules/forms/forms.client.module.js +++ b/public/modules/forms/forms.client.module.js @@ -3,5 +3,10 @@ // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('forms', [ 'ngFileUpload', 'ui.date', 'ui.sortable', +<<<<<<< HEAD + 'angular-input-stars', 'users', 'ngclipboard', 'textAngular', + 'frapontillo.bootstrap-switch' +======= 'angular-input-stars', 'users', 'ngclipboard' +>>>>>>> 2.20 ]);//, 'colorpicker.module' @TODO reactivate this module 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 d49d8914..99a1c438 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 @@ -10,7 +10,8 @@ $httpBackend, $stateParams, $location, - $state; + $state, + $timeout; var sampleUser = { firstName: 'Full', @@ -175,7 +176,7 @@ // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). // This allows us to inject a service but then attach it to a variable // with the same name as the service. - beforeEach(inject(function($controller, $rootScope, _$state_, _$location_, _$stateParams_, _$httpBackend_, CurrentForm, Forms) { + beforeEach(inject(function($controller, $rootScope, _$state_, _$location_, _$stateParams_, _$httpBackend_, CurrentForm, Forms, _$timeout_) { // Set a new global scope scope = $rootScope.$new(); @@ -187,6 +188,7 @@ $httpBackend = _$httpBackend_; $location = _$location_; $state = _$state_; + $timeout = _$timeout_; $httpBackend.whenGET(/\.html$/).respond(''); $httpBackend.whenGET('/users/me/').respond(''); @@ -197,60 +199,70 @@ }; })); - it('AdminFormController should fetch current Form when instantiated', function() { - // Run controller functionality - var controller = createAdminFormController(); + it('AdminFormController should fetch current Form when instantiated', inject(function($timeout) { + $timeout(function() { + // Run controller functionality + var controller = createAdminFormController(); - // Test scope value - expect(scope.myform).toEqualData(sampleForm); - }); - - it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', inject(function($uibModal) { - var controller = createAdminFormController(); - - //Set $state transition - $state.expectTransitionTo('listForms'); - - // Set DELETE response - $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - - //Run controller functionality - scope.openDeleteModal(); - scope.removeCurrentForm(); - - $httpBackend.flush(); - $state.ensureAllTransitionsHappened(); + // Test scope value + expect(scope.myform).toEqualData(sampleForm); + }); })); - it('$scope.update() should send a PUT request with the id of form', function() { - var controller = createAdminFormController(); + it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', inject(function($timeout, $uibModal) { + $timeout(function() { + var controller = createAdminFormController(); - //Set PUT response - $httpBackend.expect('PUT', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); + //Set $state transition + $state.expectTransitionTo('listForms'); - //Run controller functionality - scope.update(false, sampleForm, false, false); + // Set DELETE response + $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - $httpBackend.flush(); - }); + //Run controller functionality + scope.openDeleteModal(); + scope.removeCurrentForm(); - it('$scope.openDeleteModal() should open scope.deleteModal', function() { - var controller = createAdminFormController(); + $httpBackend.flush(); + $state.ensureAllTransitionsHappened(); + }); + })); - //Run controller functionality - scope.openDeleteModal(); - expect(scope.deleteModal.opened).toEqual(true); - }); + it('$scope.update() should send a PUT request with the id of form', inject(function($timeout) { + $timeout(function() { + var controller = createAdminFormController(); - it('$scope.cancelDeleteModal() should close $scope.deleteModal', inject(function($uibModal) { - var controller = createAdminFormController(); + //Set PUT response + $httpBackend.expect('PUT', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - //Run controller functionality - scope.openDeleteModal(); + //Run controller functionality + scope.update(false, sampleForm, false, false); - //Run controller functionality - scope.cancelDeleteModal(); - expect( scope.deleteModal.opened ).toEqual(false); + $httpBackend.flush(); + }); + })); + + it('$scope.openDeleteModal() should open scope.deleteModal', inject(function($timeout) { + $timeout(function() { + var controller = createAdminFormController(); + + //Run controller functionality + scope.openDeleteModal(); + expect(scope.deleteModal.opened).toEqual(true); + }); + })); + + it('$scope.cancelDeleteModal() should close $scope.deleteModal', inject(function($uibModal, $timeout) { + $timeout(function() { + var controller = createAdminFormController(); + + //Run controller functionality + scope.openDeleteModal(); + + //Run controller functionality + scope.cancelDeleteModal(); + expect( scope.deleteModal.opened ).toEqual(false); + }); })); }); }()); diff --git a/public/modules/users/controllers/authentication.client.controller.js b/public/modules/users/controllers/authentication.client.controller.js index ac2979ff..811e855f 100755 --- a/public/modules/users/controllers/authentication.client.controller.js +++ b/public/modules/users/controllers/authentication.client.controller.js @@ -11,7 +11,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca var statesToIgnore = ['', 'home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success']; $scope.signin = function() { - if($scope.forms && $scope.forms.hasOwnProperty('siginForm') && !$scope.forms.signinForm.$invalid){ + if($scope.forms && $scope.forms.signinForm.$valid){ User.login($scope.credentials).then( function(response) { Auth.login(response); @@ -40,7 +40,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca return; } - if(!$scope.forms.signupForm.$invalid){ + if($scope.forms && $scope.forms.signupForm.$valid){ User.signup($scope.credentials).then( function(response) { $state.go('signup-success'); diff --git a/scripts/setup.js b/scripts/setup.js index 551dc026..d8e5350c 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -5,7 +5,7 @@ */ process.env.NODE_ENV = 'production'; -var config = require('../config/config'), +var config = require('../config/config'), mongoose = require('mongoose'), inquirer = require('inquirer'), envfile = require('envfile'), diff --git a/server.js b/server.js index afc2cf73..725a6842 100755 --- a/server.js +++ b/server.js @@ -17,7 +17,8 @@ require('events').EventEmitter.prototype._maxListeners = 0; var config = require('./config/config'), mongoose = require('mongoose'), - chalk = require('chalk'); + chalk = require('chalk'), + nodemailer = require('nodemailer'); /** * Main application entry file. @@ -36,6 +37,16 @@ mongoose.connection.on('error', function (err) { process.exit(-1); }); +const smtpTransport = nodemailer.createTransport(config.mailer.options); + +// verify connection configuration on startup +smtpTransport.verify(function(error, success) { + if (error) { + console.error(chalk.red('Your mail configuration is incorrect: ' + error)); + process.exit(-1); + } +}); + // Init the express application var app = require('./config/express')(db);