sped up list forms and fixed analytics bugs

This commit is contained in:
David Baldwynn 2017-10-02 03:18:47 -07:00
commit 45b378d16f
42 changed files with 358 additions and 502 deletions

View File

@ -18,7 +18,6 @@ TellForm 2.0.0
- [Quickstart](#quickstart)
- [Deploying with Docker](#deploying-with-docker)
- [Testing your Application](#testing-your-application)
- [FORMA](#forma)
- [Where to Get Help](#where-to-get-help)
- [Sponsors](#sponsors)
- [Backers](#backers)
@ -167,76 +166,6 @@ To calculate your client-side test coverage with Istanbul, run the coverage task
$ grunt coverage:client
```
## FORMA
#### Prerequisite:
Before you start, make sure you have
1. [Redis](https://redis.io/) installed and running at 127.0.0.1:6379
2. [MongoDB](https://www.mongodb.com/) installed and running at 127.0.0.1:27017 (OR specify the host and port in config/env/all)
3. [Docker](https://docs.docker.com/engine/installation/) installed and running
Also make sure to install [DNS Masq](http://www.thekelleys.org.uk/dnsmasq/doc.html) or equivalent if running it locally on your computer (look at dns_masq_setup_osx for instructions on OSX)
#### Install dependencies:
```
$ npm install
$ bower install
```
#### Prepare .env file:
Create .env file at project root folder. Fill in MAILER_EMAIL_ID and MAILER_PASSWORD, and either MAILER_SERVICE_PROVIDER using a [Nodemailer Well-known service](https://nodemailer.com/smtp/well-known/) or MAILER_SMTP_HOST, MAILER_SMTP_PORT, and MAILER_SMTP_SECURE for a custom SMTP server.
```
APP_NAME=forma
APP_DESC=
APP_KEYWORDS=
NODE_ENV=development
BASE_URL=localhost:5000
PORT=5000
username=forma_admin
SIGNUP_DISABLED=false
SUBDOMAINS_DISABLED=true
DISABLE_CLUSTER_MODE=true
GOOGLE_ANALYTICS_ID=
RAVEN_DSN=
PRERENDER_TOKEN=
COVERALLS_REPO_TOKEN=
# Mail config
MAILER_EMAIL_ID=forma@data.gov.sg
MAILER_PASSWORD=some-pass
MAILER_FROM=forma@data.gov.sg
# Use this for one of Nodemailer's pre-configured service providers
MAILER_SERVICE_PROVIDER=
# Use these for a custom service provider
# Note: MAILER_SMTP_HOST will override MAILER_SERVICE_PROVIDER
MAILER_SMTP_HOST=
MAILER_SMTP_PORT=465
MAILER_SMTP_SECURE=true
```
**Note**: You can view the compatible types for MAILER_SERVICE_PROVIDER [here](https://nodemailer.com/smtp/well-known/)
#### Deploy with Docker:
Create and start mongo & redis docker container.
```
$ docker run -p 27017:27017 -d --name forma-mongo mongo
$ docker run -p 127.0.0.1:6379:6379 -d --name forma-redis redis
```
After code changes, build and start docker containers.
```
$ docker start forma-mongo && docker start forma-redis
$ docker build -t forma-tellform .
$ docker stop forma-tellform
$ docker run --rm -p 5000:5000 --link forma-redis:redis-db --link forma-mongo:db --name forma-tellform forma-tellform
```
Your application should run on port 5000 or the port you specified in your .env file, so in your browser just go to [http://localhost:5000](http://localhost:5000)
## Where to get help
[Gitter Chat](https://gitter.im/whitef0x0/tellform)

View File

@ -13,8 +13,7 @@ exports.index = function(req, res) {
};
exports.form = function(req, res) {
console.log('\n\n\nRENDERING FORM\n\n\n\n');
//Allow form to be embedded
res.set('X-Frame-Options', 'GOFORIT');

View File

@ -165,7 +165,7 @@ exports.read = function(req, res) {
* Show the current form for rendering form live
*/
var readForRender = exports.readForRender = function(req, res) {
var newForm = req.form.toJSON();
var newForm = req.form;
if (!newForm.isLive && !req.user) {
return res.status(401).send({
message: 'Form is Not Public'
@ -221,7 +221,6 @@ exports.update = function(req, res) {
form.save(function(err, savedForm) {
if (err) {
console.log(err);
res.status(405).send({
message: errorHandler.getErrorMessage(err)
});
@ -251,16 +250,19 @@ exports.delete = function(req, res) {
* Get All of Users' Forms
*/
exports.list = function(req, res) {
//Allow 'admin' user to view all forms
var searchObj = {admin: req.user};
if(req.user.isAdmin()) searchObj = {};
Form.find(searchObj)
.desc('created')
.select('title', 'language', 'submissions', 'admin', 'isLive')
.populate('admin.username', 'admin._id')
.lean()
.exec(function(err, forms) {
Form.aggregate([
{ $match: { admin: req.user._id } },
{
$project: {
admin: 1,
_id: 1,
language: 1,
isLive: 1,
title: 1,
numberOfResponses: { $size: "$submissions" }
}
}
]).exec(function(err, forms) {
if (err) {
res.status(400).send({
message: errorHandler.getErrorMessage(err)
@ -293,12 +295,12 @@ exports.formByID = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
var _form = form;
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
var _form = form;
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
req.form = _form;
req.form = _form;
return next();
}
});
@ -314,10 +316,10 @@ exports.formByIDFast = function(req, res, next, id) {
});
}
Form.findById(id)
.select('title', 'language', 'form_fields', 'startPage', 'endPage', 'hideFooter', 'isLive', 'design', 'admin', 'analytics.gaCode')
.populate()
.cache()
.select('title language form_fields startPage endPage hideFooter isLive design admin analytics.gaCode')
.populate('admin.roles', 'admin.id')
.lean()
.cache()
.exec(function(err, form) {
if (err) {
return next(err);
@ -327,13 +329,7 @@ exports.formByIDFast = function(req, res, next, id) {
});
}
else {
//Remove sensitive information from User object
var _form = form;
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
req.form = _form;
req.form = form;
return next();
}
});

View File

@ -61,24 +61,22 @@ var config_nev = function () {
config_nev();
exports.validateVerificationToken = function(req, res){
console.log(req.user);
nev.confirmTempUser(req.params.token, function(err, user) {
console.log(err);
if(err) {
return res.status(500).send( {message: err } );
}
else if (user){
return res.status(500).send( {message: err } );
} else if (user){
return res.status(200).send('User successfully verified');
}
// redirect to resend verification email
else return res.status(400).send( {message: 'Verification token is invalid or has expired'} );
else {
return res.status(400).send( {message: 'Verification token is invalid or has expired'} );
}
});
};
exports.resendVerificationEmail = function(req, res, next){
nev.resendVerificationEmail(req.body.email, function(err, userFound) {
if(err) {
console.log(errorHandler.getErrorMessage(err));
return res.status(500).send( {message: errorHandler.getErrorMessage(err) } );
}
@ -125,7 +123,6 @@ exports.signup = function(req, res) {
return res.status(200).send('An email has been sent to you. Please check it to verify your account.');
});
} else {
console.log(err);
return res.status(400).send({message: 'Error: User already exists!'});
}
});

79
app/libs/constants.js Normal file
View File

@ -0,0 +1,79 @@
'use strict';
module.exports = {
fieldTypes: ['textfield',
'date',
'email',
'link',
'legal',
'url',
'textarea',
'statement',
'welcome',
'thankyou',
'file',
'dropdown',
'scale',
'rating',
'radio',
'checkbox',
'hidden',
'yes_no',
'natural',
'stripe',
'number'],
ratingShapeTypes: ['Heart',
'Star',
'thumbs-up',
'thumbs-down',
'Circle',
'Square',
'Check Circle',
'Smile Outlined',
'Hourglass',
'bell',
'Paper Plane',
'Comment',
'Trash'],
deviceTypes: ['desktop', 'phone', 'tablet', 'other'],
languageTypes: ['en', 'fr', 'es', 'it', 'de'],
langCodeToWord: {
'en': 'English',
'fr': 'Français',
'es': 'Español',
'it': 'Italiàno',
'de': 'Deutsch'
},
wordToLangCode: {
'English': 'en',
'Français': 'fr',
'Español': 'es',
'Italiàno': 'it',
'Deutsch': 'de'
},
expressionStringTypes: ['field == static',
'field != static',
'field > static',
'field >= static',
'field <= static',
'field < static',
'field contains static',
'field !contains static',
'field begins static',
'field !begins static',
'field ends static',
'field !ends static'],
userRoleTypes: ['user', 'admin', 'superuser'],
regex: {
url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/,
hexCode: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
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,}))$/
}
};

View File

@ -11,6 +11,7 @@ var mongoose = require('mongoose'),
Random = require('random-js'),
mt = Random.engines.mt19937();
mt.autoSeed();
//Mongoose Models

View File

@ -74,6 +74,9 @@ FormSubmissionSchema.path('form_fields', {
form_fields[i].isSubmission = true;
form_fields[i].submissionId = form_fields[i]._id;
form_fields[i]._id = new mongoose.mongo.ObjectID();
delete form_fields[i].deletePreserved;
}
return form_fields;
}

View File

@ -0,0 +1,26 @@
'use strict';
const constants = require('../../libs/constants'),
config = require('../../../config/config');
module.exports = exports = function lastModifiedPlugin (schema, options) {
schema.add({
language: {
type: String,
enum: constants.languageTypes,
default: config.defaultLanguage,
required: options.required || 'Must be a valid language'
}
});
schema.pre('save', function (next) {
var currWord = this.language;
//English is the default backup language
this.language = 'en';
if(constants.wordToLangCode.has(currWord)){
this.language = constants.wordToLangCode[currWord];
}
next();
});
};

View File

@ -17,14 +17,16 @@ module.exports = function(app) {
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/forms/:formId([a-zA-Z0-9]+)')
.post(forms.createSubmission);
app.route('/subdomain/:userSubdomain((?!api$)[A-Za-z0-9]+)/forms/:formId([a-zA-Z0-9]+)/render')
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)
app.route('/forms/:formIdFast([a-zA-Z0-9]+)/render')
.get(auth.isAuthenticatedOrApiKey, forms.hasAuthorization, forms.readForRender);
} else {
app.route('/forms/:formId([a-zA-Z0-9]+)/render')
app.route('/view/')
.get(core.form);
app.route('/forms/:formIdFast([a-zA-Z0-9]+)/render')
.get(forms.readForRender);
}
app.route('/forms')

View File

@ -53,7 +53,6 @@ module.exports = function (io, socket) {
if (data.isSubmitted && !data.isSaved) {
visitorsData[current_socket.id].isSaved = true;
saveVisitorData(data, function() {
console.log("\n\n\n\n\ncurrent_socket.id: "+current_socket.id);
current_socket.disconnect(true);
});
}

View File

@ -109,9 +109,7 @@ describe('FormSubmission Model Unit Tests:', function() {
myForm.save(function(err, form){
if(err){
console.log(err.errors);
done(err);
return;
return done(err);
}
var submissionFields = _.clone(myForm.form_fields);

View File

@ -45,7 +45,6 @@ describe('User CRUD tests', function() {
.send(_User)
.expect(200)
.end(function(FormSaveErr) {
console.log('CREATING USER');
// Handle error
should.not.exist(FormSaveErr);

View File

@ -43,17 +43,19 @@
}
</style>
<script src="/static/lib/jquery/dist/jquery.slim.min.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(window).on("load", function() {
$(window).ready(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">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/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">
<!--Bower CSS dependencies-->
{% for bowerCssFile in bowerCssFiles %}
<link rel="stylesheet" href="{{bowerCssFile}}">
@ -84,17 +86,9 @@
<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 -->
<!--
Embedding The User Object signupDisabled, socketPort and socketUrl Boolean
-->
<script type="text/javascript">
var user = {{ user | json | safe }};
var signupDisabled = {{signupDisabled | safe}};
@ -107,12 +101,13 @@
</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 src="/static/lib/jquery-ui/jquery-ui.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.slim.js" async></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></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="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-date/1.0.1/date.min.js" type="text/javascript"></script>
<!--Application JavaScript Files-->
{% for jsFile in formJSFiles %}
<script type="text/javascript" src="{{jsFile}}"></script>
@ -124,20 +119,15 @@
<script async type="text/javascript" src="http://{{request.hostname}}:35729/livereload.js"></script>
{% endif %}
<script async>
<script defer>
Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
</script>
<script async>
(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)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{google_analytics_id}}', 'auto');
ga('send', 'pageview');
<script >
window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
</script>
<script src="https://www.google-analytics.com/analytics.js" async defer></script>
</body>
</html>

View File

@ -2,61 +2,62 @@
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{title}}</title>
<title>{{title}}</title>
<!-- General META -->
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- General META -->
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Semantic META -->
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<!-- Semantic META -->
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<!-- Facebook META -->
<meta property="og:site_name" content="{{title}}">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:url" content="{{url}}">
<meta property="og:image" content="/img/brand/logo.png">
<meta property="og:type" content="website">
<!-- Facebook META -->
<meta property="og:site_name" content="{{title}}">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:url" content="{{url}}">
<meta property="og:image" content="/img/brand/logo.png">
<meta property="og:type" content="website">
<!-- Twitter META -->
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:url" content="{{url}}">
<meta name="twitter:image" content="/img/brand/logo.png">
<!-- Twitter META -->
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:url" content="{{url}}">
<meta name="twitter:image" content="/img/brand/logo.png">
<!-- 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="/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'>
<!-- 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='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900'>
<!--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.css"/>
<link rel="stylesheet" href="/static/modules/core/css/github-fork-ribbon.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.css"/>
<link rel="stylesheet" href="/static/modules/core/css/github-fork-ribbon.css"/>
<!-- end Bower CSS dependencies-->
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
@ -72,11 +73,16 @@
<!--Embedding The signupDisabled Boolean-->
<script type="text/javascript">
var signupDisabled = {{signupDisabled | safe}};
var socketPort = {{socketPort | safe}} || false;
var socketPort = false;
{% if socketPort %}
socketPort = {{socketPort | safe}};
{% endif %}
var socketUrl = "{{socketUrl | safe}}" || false;
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!--Socket.io Client Dependency-->
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
@ -114,15 +120,12 @@
<![endif] -->
<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)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{google_analytics_id}}', 'auto');
ga('send', 'pageview');
</script>
window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
</script>
<script src="https://www.google-analytics.com/analytics.js" async defer></script>
</body>
</html>

View File

@ -27,11 +27,11 @@ var fs = require('fs-extra'),
var mongoose = require('mongoose');
var cacheOpts = {
max:1000,
maxAge:1000*60
max:10000,
maxAge:1000*60*2
};
require('mongoose-cache').install(mongoose, cacheOpts)
require('mongoose-cache').install(mongoose, cacheOpts);
/**
* Configure Socket.io

View File

@ -50,6 +50,7 @@
"forever": "~0.15.1",
"fs-extra": "~0.26.2",
"glob": "^7.0.3",
"google-cdn": "^1.1.0",
"grunt": "~0.4.1",
"grunt-cli": "~0.1.13",
"grunt-concurrent": "~2.3.0",

View File

@ -649,13 +649,8 @@ angular.module('TellForm.templates', []).run(['$templateCache', function($templa
$templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html",
"<section class=\"auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">Not Authorized to Access Form</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">The form you are trying to access is currently private and not accesible publically.<br>If you are the owner of the form, you can set it to \"Public\" in the \"Configuration\" panel in the form admin.</div></div></div></section>");
$templateCache.put("form_modules/forms/base/views/submit-form.client.view.html",
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n" +
" (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n" +
" m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n" +
" })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n" +
"\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto');\n" +
" ga('send', 'pageview');</script>");
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');</script><script ng-if=myform.analytics.gaCode src=https://www.google-analytics.com/analytics.js async defer></script>");
}]);
'use strict';
@ -694,7 +689,6 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope'
// add previous state property
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
$state.previous = fromState;
//console.log('toState: '+toState.name);
var statesToIgnore = ['home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success'];
@ -728,12 +722,10 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope'
if(user){
authenticator = new Authorizer(user);
//console.log('access denied: '+!authenticator.canAccess(permissions));
//console.log(permissions);
if( (permissions !== null) ){
if( !authenticator.canAccess(permissions) ){
event.preventDefault();
//console.log('access denied');
$state.go('access_denied');
}
}
@ -967,62 +959,6 @@ angular.module('core').service('Menus', [
}
]);
(function () {
'use strict';
// Create the Socket.io wrapper service
angular
.module('core')
.factory('Socket', Socket);
Socket.$inject = ['$timeout', '$window'];
function Socket($timeout, $window) {
// Connect to Socket.io server
function connect(url) {
service.socket = io(url, {'transports': ['websocket', 'polling']});
}
// Wrap the Socket.io 'emit' method
function emit(eventName, data) {
if (service.socket) {
service.socket.emit(eventName, data);
}
}
// Wrap the Socket.io 'on' method
function on(eventName, callback) {
if (service.socket) {
service.socket.on(eventName, function (data) {
$timeout(function () {
callback(data);
});
});
}
}
// Wrap the Socket.io 'removeListener' method
function removeListener(eventName) {
if (service.socket) {
service.socket.removeListener(eventName);
}
}
var service = {
connect: connect,
emit: emit,
on: on,
removeListener: removeListener,
socket: null
};
connect(window.location.protocol+'//'+window.location.hostname);
return service;
}
}());
'use strict';
angular.module('core').factory('subdomain', ['$location', function ($location) {
@ -1073,7 +1009,6 @@ angular.module('forms').run(['Menus',
};
}]).filter('trustSrc', ['$sce', function($sce){
return function(formUrl){
(' $sce.trustAsResourceUrl(formUrl): '+ $sce.trustAsResourceUrl(formUrl));
return $sce.trustAsResourceUrl(formUrl);
};
}]).config(['$provide', function ($provide){
@ -1191,9 +1126,7 @@ angular.module('users').config(['$httpProvider',
responseError: function(response) {
if( $location.path() !== '/users/me' && response.config){
if(response.config.url !== '/users/me'){
console.log('intercepted rejection of ', response.config.url, response.status);
if (response.status === 401) {
console.log($location.path());
// save the current location so that login can redirect back
$location.nextAfterLogin = $location.path();
$location.path('/signin');
@ -1342,9 +1275,9 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
Auth.login(response);
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== ''){
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== '') {
$state.go($state.previous.name);
}else{
} else {
$state.go('listForms');
}
},
@ -1360,7 +1293,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
$scope.signup = function() {
if($scope.credentials === 'admin'){
$scope.error = 'Username cannot be \'admin\'. Please pick another username.'
$scope.error = 'Username cannot be \'admin\'. Please pick another username.';
return;
}
@ -1410,7 +1343,6 @@ angular.module('users').controller('PasswordController', ['$scope', '$stateParam
User.resetPassword($scope.passwordDetails, $stateParams.token).then(
function(response){
// If successful show success message and clear form
console.log(response);
$scope.success = response.message;
$scope.passwordDetails = null;
@ -1511,11 +1443,8 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
// Submit forgotten password account id
$scope.resendVerifyEmail = function() {
// console.log($scope.credentials);
// console.log($scope.credentials.email);
User.resendVerifyEmail($scope.credentials.email).then(
function(response){
console.log(response);
$scope.success = response.message;
$scope.credentials = null;
$scope.isResetSent = true;
@ -1534,13 +1463,11 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
console.log($stateParams.token);
User.validateVerifyToken($stateParams.token).then(
function(response){
console.log('Success: '+response.message);
$scope.success = response.message;
$scope.isResetSent = true;
$scope.credentials.email = null;
},
function(error){
console.log('Error: '+error.message);
$scope.isResetSent = false;
$scope.error = error;
$scope.credentials.email = null;
@ -1570,18 +1497,11 @@ angular.module('users').factory('Auth', ['$window',
// Auth <- $http <- $resource <- LoopBackResource <- User <- Auth
ensureHasCurrentUser: function(User) {
if (service._currentUser && service._currentUser.username) {
//console.log('Using local current user.');
//console.log(service._currentUser);
return service._currentUser;
}
else if ($window.user){
//console.log('Using cached current user.');
//console.log($window.user);
} else if ($window.user){
service._currentUser = $window.user;
return service._currentUser;
}
else{
//console.log('Fetching current user from the server.');
} else{
User.getCurrent().then(function(user) {
// success
service._currentUser = user;
@ -1593,7 +1513,6 @@ angular.module('users').factory('Auth', ['$window',
userState.isLoggedIn = false;
service._currentUser = null;
$window.user = null;
console.log('User.getCurrent() err', response);
return null;
});
}
@ -1860,9 +1779,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$rootScope.saveInProgress = false;
CurrentForm.setForm($scope.myform);
console.log("$scope.myform");
console.log($scope.myform);
$scope.formURL = '/#!/forms/' + $scope.myform._id;
@ -1891,11 +1807,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
{
heading: $filter('translate')('CONFIGURE_TAB'),
templateName: 'configure'
},
/*{
heading: $filter('translate')('ANALYZE_TAB'),
templateName: 'analyze'
}*/
}
];
$scope.setForm = function(form){
@ -1924,8 +1836,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
});
$scope.deleteModal.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
@ -1946,12 +1856,8 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$http.delete('/forms/'+form_id)
.then(function(response){
console.log('form deleted successfully');
$state.go('listForms', {}, {reload: true});
$state.go('listForms', {}, {reload: true})
}, function(error){
console.log('ERROR: Form could not be deleted.');
console.error(error);
});
}
@ -1977,15 +1883,13 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
if (isDiffed) {
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {changes: data})
.then(function (response) {
if (refreshAfterUpdate) $rootScope.myform = $scope.myform = response.data;
// console.log(response.data);
if (refreshAfterUpdate) {
$rootScope.myform = $scope.myform = response.data;
}
}).catch(function (response) {
console.log('Error occured during form UPDATE.\n');
// console.log(response.data);
err = response.data;
console.error(err);
}).finally(function () {
// console.log('finished updating');
if (!updateImmediately) {
$rootScope.saveInProgress = false;
}
@ -2005,15 +1909,14 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {form: dataToSend})
.then(function (response) {
if (refreshAfterUpdate) $rootScope.myform = $scope.myform = response.data;
if (refreshAfterUpdate) {
$rootScope.myform = $scope.myform = response.data;
}
}).catch(function (response) {
console.log('Error occured during form UPDATE.\n');
// console.log(response.data);
err = response.data;
console.error(err);
}).finally(function () {
// console.log('finished updating');
if (!updateImmediately) {
$rootScope.saveInProgress = false;
}
@ -2722,9 +2625,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
$scope.table.rows = tmpArray;
})
.error(function(err){
console.log('Could not delete form submissions.\nError: ');
console.log(err);
console.error = err;
console.error(err);
});
};
@ -3589,6 +3490,7 @@ ApplicationConfiguration.registerModule('view-form', [
country: geoData.country_name
}
};
Socket.emit('form-visitor-data', visitorData);
}
@ -3597,6 +3499,10 @@ ApplicationConfiguration.registerModule('view-form', [
if (!Socket.socket) {
Socket.connect();
}
Socket.on('disconnect', function(){
Socket.connect();
});
}
var service = {
@ -3623,7 +3529,6 @@ angular.module('view-form').directive('keyToOption', function(){
var keyCode = event.which || event.keyCode;
var index = parseInt(String.fromCharCode(keyCode))-1;
//console.log($scope.field);
if (index < $scope.field.fieldOptions.length) {
event.preventDefault();
@ -3651,7 +3556,7 @@ angular.module('view-form').directive('keyToTruthy', ['$rootScope', function($ro
var keyCode = event.which || event.keyCode;
var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32;
var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32;
console.log($scope);
if(keyCode === truthyKeyCode ) {
event.preventDefault();
$scope.$apply(function() {
@ -4011,9 +3916,7 @@ angular.module('view-form').directive('fieldDirective', ['$http', '$compile', '$
}else if(type === 'rating'){
scope.field.fieldValue = 0;
}else if(scope.field.fieldType === 'radio'){
console.log(scope.field);
scope.field.fieldValue = scope.field.fieldOptions[0].option_value;
console.log(scope.field.fieldValue);
}else if(type === 'legal'){
scope.field.fieldValue = 'true';
$rootScope.nextField();
@ -4160,7 +4063,6 @@ angular.module('view-form').directive('onFinishRender', ["$rootScope", "$timeout
});
}else if(scope.$last) {
scope.$evalAsync(function () {
// console.log(broadcastMessage+'Finished');
$rootScope.$broadcast(broadcastMessage+' Finished');
});
}
@ -4236,7 +4138,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
$scope.fieldTop = elemBox.top;
$scope.fieldBottom = elemBox.bottom;
//console.log($scope.forms.myForm);
var field_id;
var field_index;
@ -4254,18 +4155,16 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
}else if( $scope.fieldBottom < 0){
} else if( $scope.fieldBottom < 0){
field_index = $scope.selected.index+1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
} else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
field_index = $scope.selected.index-1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
//console.log('$scope.selected.index: '+$scope.selected.index);
//console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom);
$scope.$apply();
$scope.$apply();
}
};
@ -4391,7 +4290,7 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
});
});
});
}else {
} else {
setTimeout(function() {
if (document.querySelectorAll('.activeField .focusOn')[0]) {
//FIXME: DAVID: Figure out how to set focus without scroll movement in HTML Dom
@ -4402,7 +4301,10 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
});
}
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
//Only send analytics data if form has not been submitted
if(!$scope.myform.submitted){
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
}
};
$rootScope.nextField = $scope.nextField = function(){
@ -4588,10 +4490,22 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
// Create the Socket.io wrapper service
function Socket($timeout, $window) {
var service;
var service = {
socket: null
};
// Connect to Socket.io server
function connect(url) {
// Connect to TellForm Socket.io server
function connect() {
var url = '';
if($window.socketUrl && $window.socketPort){
url = window.location.protocol + '//' + $window.socketUrl + ':' + $window.socketPort;
} else if ($window.socketUrl){
url = window.location.protocol + '//' + $window.socketUrl;
} else if ($window.socketPort){
url = window.location.protocol + '//' + window.location.hostname + ':' + $window.socketPort;
} else {
url = window.location.protocol + '//' + window.location.hostname;
}
service.socket = io(url, {'transports': ['websocket', 'polling']});
}
@ -4620,6 +4534,8 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
}
}
connect();
service = {
connect: connect,
emit: emit,
@ -4628,19 +4544,6 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
socket: null
};
console.log($window.socketUrl);
var url = '';
if($window.socketUrl && $window.socketPort){
url = window.location.protocol + '//' + $window.socketUrl + ':' + $window.socketPort;
} else if ($window.socketUrl){
url = window.location.protocol + '//' + $window.socketUrl;
} else if ($window.socketPort){
url = window.location.protocol + '//' + window.location.hostname + ':' + $window.socketPort;
} else {
url = window.location.protocol + '//' + window.location.hostname;
}
connect(url);
return service;
}
@ -4663,7 +4566,6 @@ angular.module('view-form').service('TimeCounter', [
this.restartClock = function(){
_startTime = Date.now();
_endTime = null;
// console.log('Clock Started');
};
this.getTimeElapsed = function(){

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -66,13 +66,8 @@ angular.module('TellForm-Form.form_templates', []).run(['$templateCache', functi
$templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html",
"<section class=\"auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">Not Authorized to Access Form</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">The form you are trying to access is currently private and not accesible publically.<br>If you are the owner of the form, you can set it to \"Public\" in the \"Configuration\" panel in the form admin.</div></div></div></section>");
$templateCache.put("form_modules/forms/base/views/submit-form.client.view.html",
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n" +
" (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n" +
" m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n" +
" })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n" +
"\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto');\n" +
" ga('send', 'pageview');</script>");
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');</script><script ng-if=myform.analytics.gaCode src=https://www.google-analytics.com/analytics.js async defer></script>");
$templateCache.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html",
"<div class=\"field row text-center\"><div class=\"col-xs-12 text-center\"><h1>{{pageData.introTitle}}</h1></div><div class=\"col-xs-10 col-xs-offset-1 text-left\"><p style=color:#ddd>{{pageData.introParagraph}}</p></div></div><div class=\"row form-actions\" style=\"padding-bottom:3em; padding-left: 1em; padding-right: 1em\"><p ng-repeat=\"button in pageData.buttons\" class=text-center style=display:inline><button class=\"btn btn-info\" type=button ng-style=\"{'background-color':button.bgColor, 'color':button.color}\"><a href={{button.url}} style=\"font-size: 1.6em; text-decoration: none; color: inherit\">{{button.text}}</a></button></p></div><div class=\"row form-actions\"><p class=\"col-xs-3 col-xs-offset-3 text-center\"><button class=\"btn btn-info\" type=button><a ng-click=exitpageData() style=\"color:white; font-size: 1.6em; text-decoration: none\">{{ 'CONTINUE_FORM' | translate }}</a></button></p></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/date.html",
@ -121,16 +116,14 @@ angular.module('view-form').config(['$stateProvider',
Forms: 'Forms',
myForm: ["Forms", "$q", "$state", "$stateParams", function (Forms, $q, $state, $stateParams) {
var deferred = $q.defer();
console.log(Forms.get({formId: $stateParams.formId}).$promise);
return Forms.get({formId: $stateParams.formId}).$promise.then(function(data) {
console.log(data);
return data;
}, function(reason) {
console.log(reason);
Forms.get({formId: $stateParams.formId}).$promise.then(function(data) {
deferred.resolve(data);
}, function(reason) {
$state.go('unauthorizedFormAccess');
return deferred.reject({redirectTo: 'unauthorizedFormAccess'});
deferred.reject({redirectTo: 'unauthorizedFormAccess'});
});
//return Forms.get({formId: $stateParams.formId}).$promise;
return deferred.promise;
}]
},
controller: 'SubmitFormController',
@ -200,6 +193,7 @@ angular.module('view-form').config(['$stateProvider',
country: geoData.country_name
}
};
Socket.emit('form-visitor-data', visitorData);
}
@ -208,6 +202,10 @@ angular.module('view-form').config(['$stateProvider',
if (!Socket.socket) {
Socket.connect();
}
Socket.on('disconnect', function(){
Socket.connect();
});
}
var service = {
@ -234,7 +232,6 @@ angular.module('view-form').directive('keyToOption', function(){
var keyCode = event.which || event.keyCode;
var index = parseInt(String.fromCharCode(keyCode))-1;
//console.log($scope.field);
if (index < $scope.field.fieldOptions.length) {
event.preventDefault();
@ -262,7 +259,7 @@ angular.module('view-form').directive('keyToTruthy', ['$rootScope', function($ro
var keyCode = event.which || event.keyCode;
var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32;
var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32;
console.log($scope);
if(keyCode === truthyKeyCode ) {
event.preventDefault();
$scope.$apply(function() {
@ -440,9 +437,7 @@ angular.module('view-form').directive('fieldDirective', ['$http', '$compile', '$
}else if(type === 'rating'){
scope.field.fieldValue = 0;
}else if(scope.field.fieldType === 'radio'){
console.log(scope.field);
scope.field.fieldValue = scope.field.fieldOptions[0].option_value;
console.log(scope.field.fieldValue);
}else if(type === 'legal'){
scope.field.fieldValue = 'true';
$rootScope.nextField();
@ -589,7 +584,6 @@ angular.module('view-form').directive('onFinishRender', ["$rootScope", "$timeout
});
}else if(scope.$last) {
scope.$evalAsync(function () {
// console.log(broadcastMessage+'Finished');
$rootScope.$broadcast(broadcastMessage+' Finished');
});
}
@ -665,7 +659,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
$scope.fieldTop = elemBox.top;
$scope.fieldBottom = elemBox.bottom;
//console.log($scope.forms.myForm);
var field_id;
var field_index;
@ -683,18 +676,16 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
}else if( $scope.fieldBottom < 0){
} else if( $scope.fieldBottom < 0){
field_index = $scope.selected.index+1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
} else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
field_index = $scope.selected.index-1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
//console.log('$scope.selected.index: '+$scope.selected.index);
//console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom);
$scope.$apply();
$scope.$apply();
}
};
@ -820,7 +811,7 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
});
});
});
}else {
} else {
setTimeout(function() {
if (document.querySelectorAll('.activeField .focusOn')[0]) {
//FIXME: DAVID: Figure out how to set focus without scroll movement in HTML Dom
@ -831,7 +822,10 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
});
}
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
//Only send analytics data if form has not been submitted
if(!$scope.myform.submitted){
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
}
};
$rootScope.nextField = $scope.nextField = function(){
@ -1017,10 +1011,22 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
// Create the Socket.io wrapper service
function Socket($timeout, $window) {
var service;
var service = {
socket: null
};
// Connect to Socket.io server
function connect(url) {
// Connect to TellForm Socket.io server
function connect() {
var url = '';
if($window.socketUrl && $window.socketPort){
url = window.location.protocol + '//' + $window.socketUrl + ':' + $window.socketPort;
} else if ($window.socketUrl){
url = window.location.protocol + '//' + $window.socketUrl;
} else if ($window.socketPort){
url = window.location.protocol + '//' + window.location.hostname + ':' + $window.socketPort;
} else {
url = window.location.protocol + '//' + window.location.hostname;
}
service.socket = io(url, {'transports': ['websocket', 'polling']});
}
@ -1049,6 +1055,8 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
}
}
connect();
service = {
connect: connect,
emit: emit,
@ -1057,19 +1065,6 @@ angular.module('view-form').factory('Forms', ['$resource', 'VIEW_FORM_URL',
socket: null
};
console.log($window.socketUrl);
var url = '';
if($window.socketUrl && $window.socketPort){
url = window.location.protocol + '//' + $window.socketUrl + ':' + $window.socketPort;
} else if ($window.socketUrl){
url = window.location.protocol + '//' + $window.socketUrl;
} else if ($window.socketPort){
url = window.location.protocol + '//' + window.location.hostname + ':' + $window.socketPort;
} else {
url = window.location.protocol + '//' + window.location.hostname;
}
connect(url);
return service;
}
@ -1092,7 +1087,6 @@ angular.module('view-form').service('TimeCounter', [
this.restartClock = function(){
_startTime = Date.now();
_endTime = null;
// console.log('Clock Started');
};
this.getTimeElapsed = function(){

File diff suppressed because one or more lines are too long

View File

@ -3,13 +3,8 @@ angular.module('TellForm-Form.form_templates', []).run(['$templateCache', functi
$templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html",
"<section class=\"auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">Not Authorized to Access Form</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">The form you are trying to access is currently private and not accesible publically.<br>If you are the owner of the form, you can set it to \"Public\" in the \"Configuration\" panel in the form admin.</div></div></div></section>");
$templateCache.put("form_modules/forms/base/views/submit-form.client.view.html",
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n" +
" (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n" +
" m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n" +
" })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n" +
"\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto');\n" +
" ga('send', 'pageview');</script>");
"<section class=public-form ng-style=\"{ 'background-color': myform.design.colors.backgroundColor }\"><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');</script><script ng-if=myform.analytics.gaCode src=https://www.google-analytics.com/analytics.js async defer></script>");
$templateCache.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html",
"<div class=\"field row text-center\"><div class=\"col-xs-12 text-center\"><h1>{{pageData.introTitle}}</h1></div><div class=\"col-xs-10 col-xs-offset-1 text-left\"><p style=color:#ddd>{{pageData.introParagraph}}</p></div></div><div class=\"row form-actions\" style=\"padding-bottom:3em; padding-left: 1em; padding-right: 1em\"><p ng-repeat=\"button in pageData.buttons\" class=text-center style=display:inline><button class=\"btn btn-info\" type=button ng-style=\"{'background-color':button.bgColor, 'color':button.color}\"><a href={{button.url}} style=\"font-size: 1.6em; text-decoration: none; color: inherit\">{{button.text}}</a></button></p></div><div class=\"row form-actions\"><p class=\"col-xs-3 col-xs-offset-3 text-center\"><button class=\"btn btn-info\" type=button><a ng-click=exitpageData() style=\"color:white; font-size: 1.6em; text-decoration: none\">{{ 'CONTINUE_FORM' | translate }}</a></button></p></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/date.html",

View File

@ -56,9 +56,7 @@ angular.module('view-form').directive('fieldDirective', ['$http', '$compile', '$
}else if(type === 'rating'){
scope.field.fieldValue = 0;
}else if(scope.field.fieldType === 'radio'){
console.log(scope.field);
scope.field.fieldValue = scope.field.fieldOptions[0].option_value;
console.log(scope.field.fieldValue);
}else if(type === 'legal'){
scope.field.fieldValue = 'true';
$rootScope.nextField();

View File

@ -18,7 +18,6 @@ angular.module('view-form').directive('onFinishRender', function ($rootScope, $t
});
}else if(scope.$last) {
scope.$evalAsync(function () {
// console.log(broadcastMessage+'Finished');
$rootScope.$broadcast(broadcastMessage+' Finished');
});
}

View File

@ -66,7 +66,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
$scope.fieldTop = elemBox.top;
$scope.fieldBottom = elemBox.bottom;
//console.log($scope.forms.myForm);
var field_id;
var field_index;
@ -84,18 +83,16 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
}else if( $scope.fieldBottom < 0){
} else if( $scope.fieldBottom < 0){
field_index = $scope.selected.index+1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
} else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) {
field_index = $scope.selected.index-1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
//console.log('$scope.selected.index: '+$scope.selected.index);
//console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom);
$scope.$apply();
$scope.$apply();
}
};

View File

@ -9,7 +9,6 @@ angular.module('view-form').service('TimeCounter', [
this.restartClock = function(){
_startTime = Date.now();
_endTime = null;
// console.log('Clock Started');
};
this.getTimeElapsed = function(){

View File

@ -4,12 +4,9 @@
<!-- User's Google Analytics -->
<script ng-if="myform.analytics.gaCode">
(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)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{myform.analytics.gaCode}}', 'auto');
ga('send', 'pageview');
window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');
</script>
<script ng-if="myform.analytics.gaCode" src="https://www.google-analytics.com/analytics.js" async defer></script>
<!-- End Google Analytics -->

View File

@ -12,13 +12,14 @@ angular.module('view-form').config(['$stateProvider',
Forms: 'Forms',
myForm: function (Forms, $q, $state, $stateParams) {
var deferred = $q.defer();
return Forms.get({formId: $stateParams.formId}).$promise.then(function(data) {
return data;
}, function(reason) {
console.error(reason);
Forms.get({formId: $stateParams.formId}).$promise.then(function(data) {
deferred.resolve(data);
}, function(reason) {
$state.go('unauthorizedFormAccess');
return deferred.reject({redirectTo: 'unauthorizedFormAccess'});
deferred.reject({redirectTo: 'unauthorizedFormAccess'});
});
return deferred.promise;
}
},
controller: 'SubmitFormController',

View File

@ -56,7 +56,6 @@
}
};
console.log('sending form-visitor-data');
Socket.emit('form-visitor-data', visitorData);
}
@ -67,7 +66,6 @@
}
Socket.on('disconnect', function(){
console.log("reconnected to socket");
Socket.connect();
});
}

View File

@ -11,7 +11,6 @@ angular.module('view-form').directive('keyToOption', function(){
var keyCode = event.which || event.keyCode;
var index = parseInt(String.fromCharCode(keyCode))-1;
//console.log($scope.field);
if (index < $scope.field.fieldOptions.length) {
event.preventDefault();

View File

@ -12,7 +12,7 @@ angular.module('view-form').directive('keyToTruthy', ['$rootScope', function($ro
var keyCode = event.which || event.keyCode;
var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32;
var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32;
console.log($scope);
if(keyCode === truthyKeyCode ) {
event.preventDefault();
$scope.$apply(function() {

View File

@ -17,7 +17,6 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope'
// add previous state property
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
$state.previous = fromState;
//console.log('toState: '+toState.name);
var statesToIgnore = ['home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success'];
@ -51,12 +50,10 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope'
if(user){
authenticator = new Authorizer(user);
//console.log('access denied: '+!authenticator.canAccess(permissions));
//console.log(permissions);
if( (permissions !== null) ){
if( !authenticator.canAccess(permissions) ){
event.preventDefault();
//console.log('access denied');
$state.go('access_denied');
}
}

View File

@ -18,9 +18,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$rootScope.saveInProgress = false;
CurrentForm.setForm($scope.myform);
console.log("$scope.myform");
console.log($scope.myform);
$scope.formURL = '/#!/forms/' + $scope.myform._id;
@ -49,11 +46,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
{
heading: $filter('translate')('CONFIGURE_TAB'),
templateName: 'configure'
},
/*{
heading: $filter('translate')('ANALYZE_TAB'),
templateName: 'analyze'
}*/
}
];
$scope.setForm = function(form){
@ -82,8 +75,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
});
$scope.deleteModal.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
@ -104,12 +95,8 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$http.delete('/forms/'+form_id)
.then(function(response){
console.log('form deleted successfully');
$state.go('listForms', {}, {reload: true});
$state.go('listForms', {}, {reload: true})
}, function(error){
console.log('ERROR: Form could not be deleted.');
console.error(error);
});
}
@ -135,15 +122,13 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
if (isDiffed) {
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {changes: data})
.then(function (response) {
if (refreshAfterUpdate) $rootScope.myform = $scope.myform = response.data;
// console.log(response.data);
if (refreshAfterUpdate) {
$rootScope.myform = $scope.myform = response.data;
}
}).catch(function (response) {
console.log('Error occured during form UPDATE.\n');
// console.log(response.data);
err = response.data;
console.error(err);
}).finally(function () {
// console.log('finished updating');
if (!updateImmediately) {
$rootScope.saveInProgress = false;
}
@ -163,15 +148,14 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {form: dataToSend})
.then(function (response) {
if (refreshAfterUpdate) $rootScope.myform = $scope.myform = response.data;
if (refreshAfterUpdate) {
$rootScope.myform = $scope.myform = response.data;
}
}).catch(function (response) {
console.log('Error occured during form UPDATE.\n');
// console.log(response.data);
err = response.data;
console.error(err);
}).finally(function () {
// console.log('finished updating');
if (!updateImmediately) {
$rootScope.saveInProgress = false;
}

View File

@ -175,9 +175,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
$scope.table.rows = tmpArray;
})
.error(function(err){
console.log('Could not delete form submissions.\nError: ');
console.log(err);
console.error = err;
console.error(err);
});
};

View File

@ -27,13 +27,6 @@
<section data-ng-controller="ListFormsController as ctrl" data-ng-init="findAll()" class="container">
<br>
<!--<div class="row">
<div class="col-xs-4 col-xs-offset-4">
<h3 class="text-center forms-list-title">
{{ 'MY_FORMS' | translate }}
</h3>
</div>
</div>-->
<div class="row">
<div ng-click="openCreateModal()" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item create-new">
<div class="title-row col-xs-12">
@ -94,7 +87,7 @@
</a>
<div class="col-xs-12 responses-row">
<small class="list-group-item-text">
<span> {{ form.submissions.length }} {{ 'RESPONSES' | translate }} </span>
<span> {{ form.numberOfResponses }} {{ 'RESPONSES' | translate }} </span>
</small>
<br>
<br>

View File

@ -23,15 +23,15 @@
border-color: none;
}*/
.public-form input.ng-valid, .public-form textarea.ng-valid {
border-color: #20FF20!important;
/*border-color: #20FF20!important;
border-style: solid!important;
border-width: 3px!important;
border-width: 3px!important;*/
}
.public-form input.ng-invalid.ng-dirty, .public-form textarea.ng-invalid.ng-dirty {
border-color: #FA787E!important;
/*border-color: #FA787E!important;
border-style: solid!important;
border-width: 3px!important;
border-width: 3px!important;*/
}
section.content p.breakwords {
@ -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 {

View File

@ -38,7 +38,6 @@ angular.module('forms').run(['Menus',
};
}]).filter('trustSrc', ['$sce', function($sce){
return function(formUrl){
(' $sce.trustAsResourceUrl(formUrl): '+ $sce.trustAsResourceUrl(formUrl));
return $sce.trustAsResourceUrl(formUrl);
};
}]).config(['$provide', function ($provide){

View File

@ -8,9 +8,7 @@ angular.module('users').config(['$httpProvider',
responseError: function(response) {
if( $location.path() !== '/users/me' && response.config){
if(response.config.url !== '/users/me'){
console.log('intercepted rejection of ', response.config.url, response.status);
if (response.status === 401) {
console.log($location.path());
// save the current location so that login can redirect back
$location.nextAfterLogin = $location.path();
$location.path('/signin');

View File

@ -13,9 +13,9 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
Auth.login(response);
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== ''){
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== '') {
$state.go($state.previous.name);
}else{
} else {
$state.go('listForms');
}
},
@ -31,7 +31,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
$scope.signup = function() {
if($scope.credentials === 'admin'){
$scope.error = 'Username cannot be \'admin\'. Please pick another username.'
$scope.error = 'Username cannot be \'admin\'. Please pick another username.';
return;
}

View File

@ -25,7 +25,6 @@ angular.module('users').controller('PasswordController', ['$scope', '$stateParam
User.resetPassword($scope.passwordDetails, $stateParams.token).then(
function(response){
// If successful show success message and clear form
console.log(response);
$scope.success = response.message;
$scope.passwordDetails = null;

View File

@ -9,11 +9,8 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
// Submit forgotten password account id
$scope.resendVerifyEmail = function() {
// console.log($scope.credentials);
// console.log($scope.credentials.email);
User.resendVerifyEmail($scope.credentials.email).then(
function(response){
console.log(response);
$scope.success = response.message;
$scope.credentials = null;
$scope.isResetSent = true;
@ -32,13 +29,11 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
console.log($stateParams.token);
User.validateVerifyToken($stateParams.token).then(
function(response){
console.log('Success: '+response.message);
$scope.success = response.message;
$scope.isResetSent = true;
$scope.credentials.email = null;
},
function(error){
console.log('Error: '+error.message);
$scope.isResetSent = false;
$scope.error = error;
$scope.credentials.email = null;

View File

@ -18,18 +18,11 @@ angular.module('users').factory('Auth', ['$window',
// Auth <- $http <- $resource <- LoopBackResource <- User <- Auth
ensureHasCurrentUser: function(User) {
if (service._currentUser && service._currentUser.username) {
//console.log('Using local current user.');
//console.log(service._currentUser);
return service._currentUser;
}
else if ($window.user){
//console.log('Using cached current user.');
//console.log($window.user);
} else if ($window.user){
service._currentUser = $window.user;
return service._currentUser;
}
else{
//console.log('Fetching current user from the server.');
} else{
User.getCurrent().then(function(user) {
// success
service._currentUser = user;
@ -41,7 +34,6 @@ angular.module('users').factory('Auth', ['$window',
userState.isLoggedIn = false;
service._currentUser = null;
$window.user = null;
console.log('User.getCurrent() err', response);
return null;
});
}