Merge pull request #229 from tellform/speed_improvements

Speed up rendering of form submission page
This commit is contained in:
David Baldwynn 2017-10-05 21:18:47 -07:00 committed by GitHub
commit d24ba0a439
19 changed files with 155 additions and 1252 deletions

View File

@ -46,17 +46,16 @@ exports.deleteSubmissions = function(req, res) {
* Submit a form entry
*/
exports.createSubmission = function(req, res) {
var form = req.form;
var timeElapsed = 0;
console.log(req.body);
if(typeof req.body.timeElapsed === 'number'){
timeElapsed = req.body.timeElapsed;
}
var submission = new FormSubmission({
admin: form.admin._id,
form: form._id,
title: form.title,
form: req.body._id,
title: req.body.title,
form_fields: req.body.form_fields,
timeElapsed: timeElapsed,
percentageComplete: req.body.percentageComplete,
@ -73,8 +72,8 @@ exports.createSubmission = function(req, res) {
message: errorHandler.getErrorMessage(err)
});
}
form.submissions.push(submission);
res.status(200).send('Form submission successfully saved');
/*form.submissions.push(submission);
form.save(function (err) {
if (err) {
@ -84,7 +83,7 @@ exports.createSubmission = function(req, res) {
});
}
res.status(200).send('Form submission successfully saved');
});
});*/
});
};
@ -94,10 +93,10 @@ exports.createSubmission = function(req, res) {
exports.listSubmissions = function(req, res) {
var _form = req.form;
FormSubmission.find({ form: _form._id }).exec(function(err, _submissions) {
FormSubmission.find({ form: _form._id }).sort('-created').lean().exec(function(err, _submissions) {
if (err) {
console.error(err);
res.status(400).send({
res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
}
@ -172,9 +171,6 @@ var readForRender = exports.readForRender = function(req, res) {
});
}
delete newForm.submissions;
//delete newForm.analytics;
delete newForm.admin;
delete newForm.lastModified;
delete newForm.__v;
delete newForm.created;
@ -190,7 +186,7 @@ var readForRender = exports.readForRender = function(req, res) {
* Update a form
*/
exports.update = function(req, res) {
var form = req.form;
var form = req.form;
var updatedForm = req.body.form;
delete updatedForm.__v;
@ -326,10 +322,9 @@ exports.formByIDFast = function(req, res, next, id) {
});
}
Form.findById(id)
.select('title language form_fields startPage endPage hideFooter isLive design admin analytics.gaCode')
.populate('admin')
.cache()
.lean()
.cache()
.select('title language form_fields startPage endPage hideFooter isLive design analytics.gaCode')
.exec(function(err, form) {
if (err) {
return next(err);

View File

@ -16,12 +16,6 @@ var FormSubmissionSchema = new Schema({
type: String
},
admin: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
form_fields: [FieldSchema],
form: {
@ -59,20 +53,19 @@ var FormSubmissionSchema = new Schema({
});
FormSubmissionSchema.pre('save', function (next) {
//Iterate through form fields and format data
//Iterate through form fields and format data
for(var i = 0; i < this.form_fields.length; i++){
if(this.form_fields[i].fieldType === 'dropdown'){
this.form_fields[i].fieldValue = this.form_fields[i].fieldValue.option_value;
}
}
next();
next();
});
FormSubmissionSchema.path('form_fields', {
set: function(form_fields){
for (var i = 0; i < form_fields.length; i++) {
form_fields[i].isSubmission = true;
form_fields[i].submissionId = form_fields[i]._id;
form_fields[i]._id = new mongoose.mongo.ObjectID();
}
return form_fields;

View File

@ -14,19 +14,22 @@ module.exports = function(app) {
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/')
.get(core.form);
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/forms/:formId([a-zA-Z0-9]+)')
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/forms/([a-zA-Z0-9]+)')
.post(forms.createSubmission);
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/forms/:formIdFast([a-zA-Z0-9]+)/render')
.get(forms.readForRender);
app.route('/forms/:formId([a-zA-Z0-9]+)/render')
.put(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.readForRender)
.get(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.readForRender);
} else {
app.route('/forms/:formIdFast([a-zA-Z0-9]+)/render')
.get(forms.readForRender);
}
app.route('/forms/:formIdFast([a-zA-Z0-9]+)')
.post(forms.createSubmission)
app.route('/forms')
.get(auth.isAuthenticatedOrApiKey, forms.list)
.post(auth.isAuthenticatedOrApiKey, forms.create);
@ -46,4 +49,5 @@ module.exports = function(app) {
// Fast formId middleware
app.param('formIdFast', forms.formByIDFast);
};

View File

@ -43,32 +43,9 @@
}
</style>
<script src="/static/lib/jquery/dist/jquery.slim.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(window).on("load", function() {
$(".loader").fadeOut("slow");
});
</script>
<!-- Fav Icon -->
<link href="/static/modules/core/img/brand/favicon.ico" rel="shortcut icon" type="image/x-icon">
<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">
<!--Bower CSS dependencies-->
{% for bowerCssFile in bowerCssFiles %}
<link rel="stylesheet" href="{{bowerCssFile}}">
{% endfor %}
<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.min.css"/>
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
@ -84,15 +61,6 @@
<section ui-view></section>
</section>
<!-- [if lt IE 9]>
<section class="browsehappy jumbotron hide">
<h1>Hello there!</h1>
<p>You are using an old browser which we unfortunately do not support.</p>
<p>Please <a href="http://browsehappy.com/">click here</a> to update your browser before using the website.</p>
<p><a href="http://browsehappy.com" class="btn btn-primary btn-lg" role="button">Yes, upgrade my browser!</a></p>
</section>
<![endif] -->
<!--Embedding The User Object signupDisabled, socketPort and socketUrl Boolean -->
<script type="text/javascript">
@ -106,13 +74,37 @@
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>
<!--Socket.io Client Dependency-->
<script src="/static/lib/socket.io-client/dist/socket.io.min.js" async></script>
<script src="/static/lib/jquery/dist/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(window).on("load", function() {
$(".loader").fadeOut("slow");
});
</script>
<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">
<!--Bower CSS dependencies-->
{% for bowerCssFile in bowerCssFiles %}
<link rel="stylesheet" href="{{bowerCssFile}}">
{% endfor %}
<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.min.css"/>
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!--Socket.io Client Dependency-->
<script src="/static/lib/socket.io-client/dist/socket.io.min.js"></script>
<script src="/static/lib/jquery-ui/jquery-ui.js" type="text/javascript"></script>
<script src="/static/dist/vendor.min.js"></script>
<script src="/static/lib/angular-ui-date/src/date.js" type="text/javascript"></script>
<script src="/static/lib/angular-ui-date/src/date.js" type="text/javascript"></script>
<!--Application JavaScript Files-->
{% for jsFile in formJSFiles %}
<script type="text/javascript" src="{{jsFile}}"></script>
@ -124,11 +116,12 @@
<script async type="text/javascript" src="http://{{request.hostname}}:35729/livereload.js"></script>
{% endif %}
<script async>
<script>
Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
</script>
<script async>
{% if google_analytics_id %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
@ -137,7 +130,13 @@
ga('create', '{{google_analytics_id}}', 'auto');
ga('send', 'pageview');
</script>
{% endif %}
<script type="text/javascript">
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");
</script>
</body>
</html>

View File

@ -126,6 +126,11 @@
ga('send', 'pageview');
</script>
<script type="text/javascript">
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");
</script>
</body>
</html>

12
config/env/all.js vendored
View File

@ -14,11 +14,6 @@ module.exports = {
pass: ''
}
},
aws: {
'accessKeyId': process.env.AWS_ACCESS_ID,
'secretAccessKey': process.env.AWS_SECRET_KEY,
'region': process.env.AWS_REGION
},
port: process.env.PORT || 3000,
socketPort: process.env.SOCKET_PORT || 20523,
@ -32,11 +27,6 @@ module.exports = {
baseUrl: '',
tempUserCollection: 'temporary_users',
mailosaur: {
key: process.env.MAILOSAUR_KEY || '',
mailbox_id: process.env.MAILOSAUR_MAILBOX || ''
},
subdomainsDisabled: (process.env.SUBDOMAINS_DISABLED === 'TRUE'),
//Sentry DSN Client Key
@ -44,7 +34,7 @@ module.exports = {
// The secret should be set to a non-guessable string that
// is used to compute a session hash
sessionSecret: 'MEAN',
sessionSecret: process.env.SESSION_SECRET || 'CHANGE_ME_PLEASE',
// The name of the MongoDB collection to store sessions in
sessionCollection: 'sessions',
// The session cookie settings

View File

@ -27,7 +27,7 @@ var fs = require('fs-extra'),
var mongoose = require('mongoose');
var cacheOpts = {
max:1000,
max:100000,
maxAge:1000*60
};
@ -201,6 +201,7 @@ module.exports = function(db) {
app.set('view cache', false);
} else if (process.env.NODE_ENV === 'production') {
app.locals.cache = 'memory';
app.set('view cache', true);
}
// Request body parsing middleware should be above methodOverride
@ -294,16 +295,16 @@ module.exports = function(db) {
// Log it
client.captureError(err);
if(process.env.NODE_ENV === 'production'){
/*if(process.env.NODE_ENV === 'production'){
res.status(500).render('500', {
error: 'Internal Server Error'
});
} else {
} else {*/
// Error page
res.status(500).render('500', {
error: err.stack
});
}
//}
});
// Assume 404 since no middleware responded

View File

@ -120,10 +120,10 @@ module.exports = function(grunt) {
productionForms: {
options: {
mangled: true,
beautify: true
compress: true
},
files: {
'public/dist/vendor_forms_uglified.js': bowerArray
'public/dist/vendor.min.js': bowerArray
}
}
},
@ -367,7 +367,7 @@ module.exports = function(grunt) {
grunt.registerTask('lint:tests', ['jshint:allTests']);
// Build task(s).
grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'ngAnnotate', 'uglify', 'closure-compiler', 'html2js:main', 'html2js:forms']);
grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'ngAnnotate', 'uglify', 'html2js:main', 'html2js:forms']);
//Setup task(s).
grunt.registerTask('setup', ['execute']);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -338,14 +338,30 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
form.timeElapsed = _timeElapsed;
form.percentageComplete = $filter('formValidity')($scope.myform) / $scope.myform.visible_form_fields.length * 100;
delete form.endPage
delete form.isLive
delete form.provider
delete form.startPage
delete form.visible_form_fields;
delete form.analytics;
delete form.design;
delete form.submissions;
delete form.submitted;
for(var i=0; i < $scope.myform.form_fields.length; i++){
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 () {

View File

@ -5,12 +5,12 @@
<div ng-show="!myform.submitted && myform.startPage.showStart" class="form-submitted" style="padding-top: 35vh;">
<div class="row">
<div class="col-xs-12 text-center" style="overflow-wrap: break-word;">
<h1 style="font-weight: 400; nont-size: 25px;">
<h1 style="font-weight: 400; nont-size: 25px;" ng-style="{'color': form.design.colors.questionColor}">
{{myform.startPage.introTitle}}
</h1>
</div>
<div class="col-xs-10 col-xs-offset-1 text-center" style="overflow-wrap: break-word;">
<p style="color: grey; font-weight: 100; font-size: 16px;">
<p style="font-weight: 100; font-size: 16px;" ng-style="{'color': form.design.colors.questionColor}">
{{myform.startPage.introParagraph}}
</p>
</div>
@ -102,7 +102,7 @@
<!-- Default End Page View -->
<div ng-if="myform.submitted && !loading && !myform.endPage.showEnd" class="form-submitted" ng-style="{'color':myform.design.colors.buttonTextColor}" style="padding-top: 5vh;">
<div class="field row text-center">
<div class="field row text-center" ng-style="{'color': myform.design.colors.questionColor}">
<div class="col-xs-12 col-sm-12 col-md-6 col-md-offset-3 text-center">{{ 'FORM_SUCCESS' | translate }}</div>
</div>
<div class="row form-actions">
@ -118,12 +118,12 @@
<div ng-if="myform.submitted && !loading && myform.endPage.showEnd" class="form-submitted" ng-style="{'color':myform.design.colors.buttonTextColor}" style="padding-top: 5vh;">
<div class="row">
<div class="col-xs-12 text-center" style="overflow-wrap: break-word;">
<h1 style="font-weight: 400; nont-size: 25px;">
<h1 style="font-weight: 400; font-size: 25px;" ng-style="{'color': myform.design.colors.questionColor}">
{{myform.endPage.title}}
</h1>
</div>
<div class="col-xs-10 col-xs-offset-1 text-center" style="overflow-wrap: break-word;">
<p style="color: grey; font-weight: 100; font-size: 16px;">
<p style="font-weight: 100; font-size: 16px;" ng-style="{'color': myform.design.colors.questionColor}">
{{myform.endPage.paragraph}}
</p>
</div>
@ -147,4 +147,4 @@
</button>
</p>
</div>
</div>
</div>

View File

@ -16,7 +16,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
rows: []
};
var submissions = $scope.myform.submissions || [];
var submissions = $scope.myform.submissions || [];
//Iterate through form's submissions
for(var i = 0; i < submissions.length; i++){

View File

@ -247,7 +247,7 @@ section.public-form {
padding: 0 10% 0 10%;
}
section.public-form .form-submitted {
height: 100%;
height: 100vh;
}
section.public-form .btn {