fixed analytics geolocation
This commit is contained in:
parent
00054c9440
commit
8a12f4d65c
|
@ -54,26 +54,19 @@ exports.createSubmission = function(req, res) {
|
|||
timeElapsed = req.body.timeElapsed;
|
||||
}
|
||||
var submission = new FormSubmission({
|
||||
admin: req.form.admin._id,
|
||||
form: req.form._id,
|
||||
title: req.form.title,
|
||||
admin: form.admin._id,
|
||||
form: form._id,
|
||||
title: form.title,
|
||||
form_fields: req.body.form_fields,
|
||||
timeElapsed: timeElapsed,
|
||||
percentageComplete: req.body.percentageComplete
|
||||
percentageComplete: req.body.percentageComplete,
|
||||
ipAddr: req.body.ipAddr,
|
||||
geoLocation: req.body.geoLocation,
|
||||
device: req.body.device
|
||||
});
|
||||
|
||||
//Save submitter's IP Address
|
||||
if(req.headers['x-forwarded-for'] || req.connection.remoteAddress){
|
||||
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
||||
if(ip && process.env.NODE_ENV !== 'development') submission.ipAddr = ip;
|
||||
}
|
||||
|
||||
if (req.device) {
|
||||
submission.device = req.device;
|
||||
}
|
||||
|
||||
submission.save(function(err, submission){
|
||||
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
return res.status(500).send({
|
||||
|
@ -185,6 +178,7 @@ exports.readForRender = function(req, res) {
|
|||
delete newForm.submissions;
|
||||
delete newForm.analytics;
|
||||
delete newForm.isLive;
|
||||
delete newForm.admin;
|
||||
|
||||
return res.json(newForm);
|
||||
};
|
||||
|
@ -234,7 +228,6 @@ exports.update = function(req, res) {
|
|||
*/
|
||||
exports.delete = function(req, res) {
|
||||
var form = req.form;
|
||||
// console.log('deleting form');
|
||||
Form.remove({_id: form._id}, function(err) {
|
||||
if (err) {
|
||||
res.status(400).send({
|
||||
|
|
|
@ -234,8 +234,8 @@ FormSchema.virtual('analytics.fields').get(function () {
|
|||
|
||||
var totalViews = dropoffViews+continueViews;
|
||||
var responses = continueViews;
|
||||
var continueRate = continueViews/totalViews*100;
|
||||
var dropoffRate = dropoffViews/totalViews*100;
|
||||
var continueRate = (continueViews/totalViews*100).toFixed(0);
|
||||
var dropoffRate = (dropoffViews/totalViews*100).toFixed(0);
|
||||
|
||||
fieldDropoffs[i] = {
|
||||
dropoffViews: dropoffViews,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema,
|
||||
freegeoip = require('node-freegeoip'),
|
||||
_ = require('lodash'),
|
||||
config = require('../../config/config'),
|
||||
path = require('path'),
|
||||
|
@ -53,9 +52,6 @@ var FormSubmissionSchema = new Schema({
|
|||
Country: {
|
||||
type: String
|
||||
},
|
||||
Region: {
|
||||
type: String
|
||||
},
|
||||
City: {
|
||||
type: String
|
||||
}
|
||||
|
@ -69,29 +65,11 @@ var FormSubmissionSchema = new Schema({
|
|||
}
|
||||
},
|
||||
|
||||
pdfFilePath: {
|
||||
type: Schema.Types.Mixed
|
||||
},
|
||||
pdf: {
|
||||
type: Schema.Types.Mixed
|
||||
},
|
||||
fdfData: {
|
||||
type: Schema.Types.Mixed
|
||||
},
|
||||
|
||||
timeElapsed: {
|
||||
type: Number
|
||||
},
|
||||
percentageComplete: {
|
||||
type: Number
|
||||
},
|
||||
|
||||
|
||||
hasPlugins: {
|
||||
oscarhost: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -112,19 +90,4 @@ FormSubmissionSchema.plugin(mUtilities.timestamp, {
|
|||
useVirtual: false
|
||||
});
|
||||
|
||||
//Check for IP Address of submitting person
|
||||
FormSubmissionSchema.pre('save', function (next) {
|
||||
var self = this;
|
||||
if (this.ipAddr) {
|
||||
if (this.isModified('ipAddr') || !this.geoLocation) {
|
||||
freegeoip.getLocation(this.ipAddr, function (err, location) {
|
||||
if (err) return next(err);
|
||||
self.geoLocation = location;
|
||||
return next();
|
||||
});
|
||||
}
|
||||
}
|
||||
return next();
|
||||
});
|
||||
|
||||
module.exports = FormSubmissionSchema;
|
||||
|
|
10
config/env/test.js
vendored
10
config/env/test.js
vendored
|
@ -56,15 +56,5 @@ module.exports = {
|
|||
pass: process.env.MAILER_PASSWORD || ''
|
||||
}
|
||||
}
|
||||
},
|
||||
oscarhost: {
|
||||
baseUrl: process.env.OSCARHOST_BASEURL || 'OSCARHOST_BASEURL',
|
||||
settings: {
|
||||
updateType: process.env.OSCARHOST_UPDATETYPE || 'OSCARHOST_UPDATETYPE',
|
||||
},
|
||||
auth:{
|
||||
user: process.env.OSCARHOST_USER || 'process.env.OSCARHOST_USER',
|
||||
pass: process.env.OSCARHOST_PASS || 'process.env.OSCARHOST_PASS',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
"mongoose-utilities": "~0.1.1",
|
||||
"morgan": "~1.6.1",
|
||||
"multer": "~1.1.0",
|
||||
"node-freegeoip": "0.0.1",
|
||||
"nodemailer": "~1.10.0",
|
||||
"nodemailer-sendgrid-transport": "^0.2.0",
|
||||
"nodemailer-sparkpost-transport": "^1.0.0",
|
||||
|
|
124
public/dist/application.js
vendored
124
public/dist/application.js
vendored
File diff suppressed because one or more lines are too long
10
public/dist/application.min.js
vendored
10
public/dist/application.min.js
vendored
File diff suppressed because one or more lines are too long
142
public/dist/form-application.js
vendored
142
public/dist/form-application.js
vendored
File diff suppressed because one or more lines are too long
8
public/dist/form-application.min.js
vendored
8
public/dist/form-application.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -260,8 +260,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
|
|||
});
|
||||
}
|
||||
|
||||
console.log("time elapsed: ");
|
||||
console.log(TimeCounter.getTimeElapsed());
|
||||
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
|
||||
};
|
||||
|
||||
|
@ -310,6 +308,39 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
|
|||
document.querySelectorAll('.ng-invalid.focusOn')[0].focus();
|
||||
};
|
||||
|
||||
var getDeviceData = function(){
|
||||
var md = new MobileDetect(window.navigator.userAgent);
|
||||
var deviceType = 'other';
|
||||
|
||||
if (md.tablet()){
|
||||
deviceType = 'tablet';
|
||||
} else if (md.mobile()) {
|
||||
deviceType = 'mobile';
|
||||
} else if (!md.is('bot')) {
|
||||
deviceType = 'desktop';
|
||||
}
|
||||
|
||||
return {
|
||||
type: deviceType,
|
||||
name: window.navigator.platform
|
||||
}
|
||||
};
|
||||
|
||||
var getIpAndGeo = function(){
|
||||
//Get Ip Address and GeoLocation Data
|
||||
$.ajaxSetup( { "async": false } );
|
||||
var geoData = $.getJSON('//freegeoip.net/json/').responseJSON;
|
||||
$.ajaxSetup( { "async": true } );
|
||||
|
||||
return {
|
||||
ipAddr: geoData.ip,
|
||||
geoLocation: {
|
||||
City: geoData.city,
|
||||
Country: geoData.country_name
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.submitForm = $scope.submitForm = function() {
|
||||
|
||||
var _timeElapsed = TimeCounter.stopClock();
|
||||
|
@ -317,8 +348,15 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
|
|||
|
||||
var form = _.cloneDeep($scope.myform);
|
||||
|
||||
form.timeElapsed = _timeElapsed;
|
||||
var deviceData = getDeviceData();
|
||||
form.device = deviceData;
|
||||
|
||||
var geoData = getIpAndGeo();
|
||||
form.ipAddr = geoData.ipAddr;
|
||||
form.geoLocation = geoData.geoLocation;
|
||||
console.log(geoData);
|
||||
|
||||
form.timeElapsed = _timeElapsed;
|
||||
form.percentageComplete = $filter('formValidity')($scope.myform) / $scope.myform.visible_form_fields.length * 100;
|
||||
delete form.visible_form_fields;
|
||||
|
||||
|
@ -331,7 +369,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
|
|||
setTimeout(function () {
|
||||
$scope.submitPromise = $http.post('/forms/' + $scope.myform._id, form)
|
||||
.success(function (data, status, headers) {
|
||||
console.log($scope.myform.form_fields[0]);
|
||||
$scope.myform.submitted = true;
|
||||
$scope.loading = false;
|
||||
SendVisitorData.send($scope.myform, getActiveField(), _timeElapsed);
|
||||
|
|
|
@ -41,7 +41,11 @@
|
|||
timeElapsed: timeElapsed,
|
||||
language: lang,
|
||||
deviceType: deviceType,
|
||||
ipAddr: geoData.ip
|
||||
ipAddr: geoData.ip,
|
||||
geoLocation: {
|
||||
city: geoData.city,
|
||||
country: geoData.country_name
|
||||
}
|
||||
};
|
||||
Socket.emit('form-visitor-data', visitorData);
|
||||
}
|
||||
|
|
|
@ -12,82 +12,12 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt
|
|||
formFields:'@'
|
||||
},
|
||||
controller: function($scope){
|
||||
console.log($scope.myform);
|
||||
if( CurrentForm.getForm().plugins){
|
||||
if(CurrentForm.getForm().plugins.oscarhost.baseUrl) $scope.oscarhostAPI = true;
|
||||
}else{
|
||||
$scope.oscarhostAPI = false;
|
||||
}
|
||||
$scope.log = '';
|
||||
$scope.pdfLoading = false;
|
||||
$scope.languages = $rootScope.languages;
|
||||
|
||||
this._current_upload = null;
|
||||
$scope.resetForm = $rootScope.resetForm;
|
||||
$scope.update = $rootScope.update;
|
||||
|
||||
this._unbindedPdfFields = $scope.pdfFields;
|
||||
|
||||
//DAVID: TODO: finish this so we can create a Form.pdfFieldMap
|
||||
// $scope.getUnbindedPdfFields = function(fieldType){
|
||||
// this._unbindedPdfFields = $scope.pdfFields
|
||||
// }
|
||||
|
||||
//PDF Functions
|
||||
$scope.cancelUpload = function(){
|
||||
this._current_upload.abort();
|
||||
$scope.pdfLoading = false;
|
||||
$scope.removePDF();
|
||||
};
|
||||
|
||||
$scope.removePDF = function(){
|
||||
$scope.myform.pdf = null;
|
||||
$scope.myform.isGenerated = false;
|
||||
$scope.myform.autofillPDFs = false;
|
||||
|
||||
console.log('form.pdf: '+$scope.myform.pdf+' REMOVED');
|
||||
};
|
||||
|
||||
$scope.uploadPDF = function(file) {
|
||||
|
||||
if (file) {
|
||||
console.log(file);
|
||||
|
||||
Upload.upload({
|
||||
url: '/upload/pdf',
|
||||
data: {
|
||||
'user': $scope.user,
|
||||
file: file
|
||||
}
|
||||
}).then(function (resp) {
|
||||
var data = resp.data;
|
||||
$scope.log = 'file ' + data.originalname + ' uploaded as ' + data.filename + '. JSON: ' + JSON.stringify(data) + '\n' + $scope.log;
|
||||
$scope.myform.pdf = angular.fromJson(angular.toJson(data));
|
||||
|
||||
//console.log($scope.myform.pdf);
|
||||
|
||||
$scope.pdfLoading = false;
|
||||
|
||||
console.log($scope.log);
|
||||
if (!$scope.$$phase && !$scope.$digest) {
|
||||
$scope.$apply();
|
||||
}
|
||||
}, function(resp){
|
||||
$scope.pdfLoading = false;
|
||||
console.log('Error occured during upload.\n');
|
||||
console.log(resp.status);
|
||||
}, function (evt) {
|
||||
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
|
||||
$scope.log = 'progress: ' + progressPercentage + '% ' +
|
||||
evt.config.data.file.name + '\n' + $scope.log;
|
||||
|
||||
console.log($scope.log);
|
||||
|
||||
$scope.pdfLoading = true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||
}
|
||||
|
||||
$scope.table.rows = submissions;
|
||||
|
||||
console.log(submissions);
|
||||
|
||||
/*
|
||||
** Analytics Functions
|
||||
|
@ -55,7 +55,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||
|
||||
if(numSubmissions == 0) return 0;
|
||||
|
||||
return totalTime/numSubmissions;
|
||||
return (totalTime/numSubmissions).toFixed(0);
|
||||
})();
|
||||
|
||||
$scope.DeviceStatistics = (function(){
|
||||
|
@ -86,12 +86,12 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||
|
||||
stats[deviceType].total_time = stats[deviceType].total_time + visitor.timeElapsed;
|
||||
|
||||
stats[deviceType].average_time = stats[deviceType].total_time / stats[deviceType].visits;
|
||||
stats[deviceType].average_time = (stats[deviceType].total_time / stats[deviceType].visits).toFixed(0);
|
||||
if(!stats[deviceType].average_time) stats[deviceType].average_time = 0;
|
||||
|
||||
if (visitor.isSubmitted) stats[deviceType].responses++;
|
||||
|
||||
stats[deviceType].completion = stats[deviceType].responses / stats[deviceType].visits;
|
||||
stats[deviceType].completion = (stats[deviceType].responses / stats[deviceType].visits).toFixed(0);
|
||||
if(!stats[deviceType].completion) stats[deviceType].completion = 0;
|
||||
}
|
||||
console.log("stats");
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
{{ 'COMPLETION_RATE' | translate }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{DeviceStatistics.desktop.completion}}
|
||||
{{DeviceStatistics.desktop.completion}}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -143,7 +143,7 @@
|
|||
{{ 'COMPLETION_RATE' | translate }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{DeviceStatistics.tablet.completion}}
|
||||
{{DeviceStatistics.tablet.completion}}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -152,7 +152,7 @@
|
|||
{{ 'COMPLETION_RATE' | translate }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{DeviceStatistics.phone.completion}}
|
||||
{{DeviceStatistics.phone.completion}}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
|||
{{ 'COMPLETION_RATE' | translate }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{DeviceStatistics.other.completion}}
|
||||
{{DeviceStatistics.other.completion}}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -245,17 +245,17 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="col-xs-2 col-xs-offset-4 text-right">
|
||||
<button class="btn btn-default" ng-click="exportSubmissions('xml')">
|
||||
<button class="btn btn-gray" ng-click="exportSubmissions('xml')">
|
||||
<small>{{ 'EXPORT_TO_EXCEL' | translate }}</small>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<button class="btn btn-default" ng-click="exportSubmissions('csv')">
|
||||
<button class="btn btn-gray" ng-click="exportSubmissions('csv')">
|
||||
<small>{{ 'EXPORT_TO_CSV' | translate }}</small>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<button class="btn btn-default" ng-click="exportSubmissions('json')">
|
||||
<button class="btn btn-gray" ng-click="exportSubmissions('json')">
|
||||
<small>{{ 'EXPORT_TO_JSON' | translate }}</small>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -290,9 +290,6 @@
|
|||
<th>
|
||||
{{ 'DATE_SUBMITTED' | translate }} (UTC)
|
||||
</th>
|
||||
<th ng-if="myform.autofillPDFs">
|
||||
{{ 'GENERATED_PDF' | translate }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
@ -318,7 +315,7 @@
|
|||
{{row.device.name}}, {{row.device.type}}
|
||||
</td>
|
||||
<td>
|
||||
{{row.geoLocation.city}}, {{row.geoLocation.country_name}}
|
||||
{{row.geoLocation.City}}, {{row.geoLocation.Country}}
|
||||
</td>
|
||||
<td>
|
||||
{{row.ipAddr}}
|
||||
|
@ -326,9 +323,6 @@
|
|||
<td>
|
||||
{{row.created | date:'yyyy-MM-dd HH:mm:ss'}}
|
||||
</td>
|
||||
<td ng-if="row.pdf">
|
||||
<a href="{{row.pdfFilePath}}" download="{{row.pdf.name}}" target="_self">{{ 'GENERATED_PDF' | translate }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
Loading…
Reference in a new issue