Merge branch 'master' into update-readme-missing-bower-cmd

This commit is contained in:
David Baldwynn 2017-08-07 15:47:11 -07:00 committed by GitHub
commit 1eebdc81d1
33 changed files with 2772 additions and 2929 deletions

View file

@ -2,7 +2,6 @@ language: node_js
dist: trusty
sudo: false
node_js:
- "5.0.0"
- "6.11.1"
env:
- NODE_ENV=travis TRAVIS=travis CXX=g++-4.8

View file

@ -23,7 +23,11 @@ var getUniqueErrorMessage = function(err) {
exports.getErrorMessage = function(err) {
var message = '';
if (err.code) {
if(!err) {
return '';
} else if(typeof err === 'string'){
message = err;
} else if (err.code) {
switch (err.code) {
case 11000:
case 11001:

View file

@ -198,6 +198,10 @@ var readForRender = exports.readForRender = function(req, res) {
*/
exports.update = function(req, res) {
var form = req.form;
var updatedForm = req.body.form;
delete updatedForm.__v;
delete updatedForm.created;
if (req.body.changes) {
var formChanges = req.body.changes;
@ -207,8 +211,8 @@ exports.update = function(req, res) {
});
} else {
//Unless we have 'admin' privileges, updating form admin is disabled
if(req.body.form && req.user.roles.indexOf('admin') === -1) {
delete req.body.form.admin;
if(updatedForm && req.user.roles.indexOf('admin') === -1) {
delete updatedForm.admin;
}
if(form.analytics === null){
@ -224,12 +228,13 @@ exports.update = function(req, res) {
delete field._id;
}
}
form = _.extend(form, req.body.form);
form = _.extend(form, updatedForm);
}
form.save(function(err, savedForm) {
if (err) {
res.status(405).send({
console.log(err);
res.status(405).send({
message: errorHandler.getErrorMessage(err)
});
} else {

View file

@ -19,6 +19,7 @@ var config_nev = function () {
nev.configure({
persistentUserModel: User,
tempUserCollection: config.tempUserCollection,
emailAndUsernameUnique: true,
expirationTime: 86400, // 24 hours
verificationURL: config.baseUrl+'/#!/verify/${URL}',
@ -103,10 +104,10 @@ exports.signup = function(req, res) {
// Add missing user fields
user.provider = 'local';
// Then save the temporary user
nev.createTempUser(user, function (err, existingPersistentUser, newTempUser) {
if (err) {
debugger;
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
@ -125,6 +126,7 @@ 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!'});
}
});

View file

@ -256,9 +256,14 @@ FormSchema.virtual('analytics.fields').get(function () {
}
var totalViews = dropoffViews+continueViews;
var continueRate = (continueViews/totalViews*100).toFixed(0);
var dropoffRate = (dropoffViews/totalViews*100).toFixed(0);
var continueRate = 0;
var dropoffRate = 0;
if(totalViews > 0){
continueRate = (continueViews/totalViews*100).toFixed(0);
dropoffRate = (dropoffViews/totalViews*100).toFixed(0);
}
fieldDropoffs[i] = {
dropoffViews: dropoffViews,
responses: continueViews,
@ -349,9 +354,6 @@ FormSchema.pre('save', function (next) {
old_ids = _.map(_.map(old_form_fields, 'globalId'), function(id){ return ''+id;}),
deletedIds = getDeletedIndexes(old_ids, new_ids);
console.log(deletedIds);
console.log(new_ids);
console.log(old_ids);
//Check if any form_fileds were deleted
if( deletedIds.length > 0 ){
@ -415,9 +417,7 @@ FormSchema.pre('save', function (next) {
submission.form_fields = submission_form_fields;
that.form_fields = currentform_form_fields;
submission.save(function (saveErr) {
return callback(saveErr);
});
return callback(null);
}, function (err) {
return cb(err);
});

View file

@ -98,7 +98,10 @@
<script type="text/javascript">
var user = {{ user | json | safe }};
var signupDisabled = {{signupDisabled | safe}};
var socketPort = {{socketPort | safe}};
var socketPort = false;
{% if socketPort %}
socketPort = {{socketPort | safe }};
{% endif %}
var socketUrl = "{{socketUrl | safe}}";
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>
@ -106,9 +109,10 @@
<!--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="/static/dist/vendor.min.js"></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>

View file

@ -72,8 +72,8 @@
<!--Embedding The signupDisabled Boolean-->
<script type="text/javascript">
var signupDisabled = {{signupDisabled | safe}};
var socketPort = {{socketPort | safe}};
var socketUrl = "{{socketUrl | safe}}";
var socketPort = {{socketPort | safe}} || false;
var socketUrl = "{{socketUrl | safe}}" || false;
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>

View file

@ -12,7 +12,7 @@
"dependencies": {
"bootstrap": "^3.3.7",
"angular-resource": "~1.4.7",
"angular-cache-buster": "~0.4.3",
"angular-cache-buster": "~0.4.3",
"angular-mocks": "~1.4.7",
"angular-bootstrap": "~0.14.3",
"angular-ui-utils": "~3.0.0",
@ -49,7 +49,10 @@
"angular": "1.4.14",
"angular-ui-select": "compiled",
"jspdf": "~1.0.178",
"angular-sanitize": "1.4.14"
"angular-sanitize": "1.4.14",
"angular-ui-sortable": "^0.17.1",
"angular-ui-date": "~0.0.11",
"angular-input-stars-directive": "master"
},
"overrides": {
"BOWER-PACKAGE": {

View file

@ -56,13 +56,15 @@ module.exports = function(db) {
app.locals.subdomainsDisabled = config.subdomainsDisabled;
if(config.socketPort){
if(config.socketPort && process.env.NODE_ENV !== 'production'){
app.locals.socketPort = config.socketPort;
} else {
app.locals.socketPort = "";
}
if(config.socketUrl){
app.locals.socketUrl = config.socketUrl;
}
}
app.locals.bowerJSFiles = config.getBowerJSAssets();
app.locals.bowerCssFiles = config.getBowerCSSAssets();

View file

@ -13,8 +13,8 @@
"url": "https://github.com/whitef0x0/tellform.git"
},
"engines": {
"node": ">=5.0.0",
"npm": ">=3.3.6"
"node": "6.11.1",
"npm": "3.3.6"
},
"scripts": {
"addcontrib": "all-contributors add",

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

@ -64,7 +64,7 @@ angular.module('view-form').directive('fieldDirective', ['$http', '$compile', '$
$rootScope.nextField();
}
};
scope.nextField = $rootScope.nextField;
scope.setActiveField = $rootScope.setActiveField;
//Set format only if field is a date

View file

@ -24,7 +24,6 @@
ng-required="field.required"
ng-disabled="field.disabled"
placeholder="MM/DD/YYYY"
ng-focus="setActiveField(field._id, index, true)"
on-tab-key="nextField()"
on-tab-and-shift-key="prevField()"
ng-change="$root.nextField()">

View file

@ -1,38 +0,0 @@
<div class="field row" ng-if="form.autofillPDFs" ng-click="setActiveField(field._id, index, true)">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<small class="field-number">
{{index+1}}
<i class="fa fa-angle-double-right" aria-hidden="true"></i>
</small>
{{field.title}}
<span class="required-error" ng-show="!field.required">{{ 'OPTIONAL' | translate }}</span>
</h3>
</div>
<div class="col-sm-8 field-input">
<div class="input-group ">
<div tabindex="-1" class="form-control file-caption">
<span class="file-caption-ellipsis" ng-if="!form.pdf"></span>
<div class="file-caption-name" ng-if="form.pdf">
{{field.file.originalname}}
</div>
</div>
<div class="input-group-btn">
<button type="button" ng-if="field.file" ng-click="removeFile(field);" title="Clear selected files" class="btn btn-danger fileinput-remove fileinput-remove-button">
<i class="glyphicon glyphicon-trash" ></i>
{{ 'DELETE' | translate }}
</button>
<button type="button" ng-if="field.fileLoading" title="Abort ongoing upload" class="btn btn-default" ng-click="cancelFileUpload(field)">
<i class="glyphicon glyphicon-ban-circle"></i>
{{ 'CANCEL' | translate }}
</button>
<div class="btn btn-success btn-file" ngf-select ngf-change="uploadPDF($files)" ng-if="!field.file">
<i class="glyphicon glyphicon-upload"></i>
{{ UPLOAD_FILE | translate }}
</div>
</div>
</div>
</div>
</div>

View file

@ -1,6 +1,7 @@
<div class="field row radio legal"
on-enter-or-tab-key="nextField()"
key-to-truthy key-char-truthy="y" key-char-falsey="n" field="field">
on-tab-and-shift-key="prevField()"
key-to-truthy key-char-truthy="y" key-char-falsey="n" field="field" on-valid-key="nextField()">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3>
<small class="field-number">
@ -14,20 +15,17 @@
<p class="col-xs-12">{{field.description}}</p>
</div>
<div class="col-xs-12 field-input container">
<div class="row-fluid"
on-enter-or-tab-key="nextField()"
on-tab-and-shift-key="prevField()">
<div class="row-fluid">
<label class="btn col-md-5 col-xs-12"
ng-class="{activeBtn: field.fieldValue == 'true'}">
<input class="focusOn"
ng-focus="setActiveField(field._id, index, true)"
ng-style="{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}"
type="radio" value="true"
ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }"
ng-required="field.required"
ng-disabled="field.disabled"
ng-change="$root.nextField()"/>
ng-change="nextField()"/>
<div class="letter" style="float:left">
Y
</div>
@ -42,7 +40,7 @@
ng-model-options="{ debounce: 250 }"
ng-required="field.required"
ng-disabled="field.disabled"
ng-change="$root.nextField()"/>
ng-change="nextField()"/>
<div class="letter" style="float:left">
N
</div>

View file

@ -26,7 +26,6 @@
</div>
<input ng-style="{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}"
type="radio" class="focusOn"
ng-focus="setActiveField(field._id, index, true)"
value="{{option.option_value}}"
ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }"

View file

@ -17,7 +17,8 @@
<input-stars max="{{field.ratingOptions.steps}}"
ng-init="field.fieldValue = 1"
on-star-click="$root.nextField()"
on-shape-click="true"
on-star-click="nextField()"
icon-full="{{field.ratingOptions.shape}}"
icon-base="fa fa-3x"
icon-empty="{{field.ratingOptions.shape}}"
@ -27,7 +28,6 @@
ng-disabled="field.disabled"
on-enter-or-tab-key="nextField()"
on-tab-and-shift-key="prevField()"
ng-focus="setActiveField(field._id, index, true)"
class="angular-input-stars focusOn">
</input-stars>
</div>

View file

@ -1,7 +1,6 @@
<div class="statement field row"
on-enter-or-tab-key="nextField()"
on-tab-and-shift-key="prevField()"
ng-focus="setActiveField(field._id, index, true)">
on-tab-and-shift-key="prevField()">
<div class="row field-title field-title">
<div class="col-xs-1"><i class="fa fa-quote-left fa-1"></i></div>
<h2 class="text-left col-xs-9">{{field.title}}</h2>
@ -13,10 +12,9 @@
<p class="col-xs-12" ng-if="field.description.length">{{field.description}} </p>
<br>
<div class="col-xs-offset-1 col-xs-11">
<button class="btn focusOn"
<button class="btn focusOn">
ng-style="{'font-size': '1.3em', 'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}"
ng-focused="setActiveField(field._id, index, true)"
ng-click="$root.nextField()">
ng-click="nextField()">
{{ 'CONTINUE' | translate }}
</button>
</div>

View file

@ -22,7 +22,6 @@
value="{{field.fieldValue}}"
ng-required="field.required"
ng-disabled="field.disabled"
ng-focus="setActiveField(field._id, index, true)"
on-enter-or-tab-key="nextField()"
on-tab-and-shift-key="prevField()"
style="border: none; border-left: lightgrey dashed 2px;">

View file

@ -29,7 +29,6 @@
ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }"
value="field.fieldValue"
ng-focus="setActiveField(field._id, index, true)"
on-enter-or-tab-key="nextField()"
on-tab-and-shift-key="prevField()"
ng-required="field.required"
@ -41,7 +40,7 @@
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
<span ng-if="field.fieldType == 'email'"> {{ 'ERROR_EMAIL_INVALID' | translate }} </span>
<span ng-if="field.validateRegex"> {{ 'ERROR_NOT_A_NUMBER' | translate }} </span>
<span ng-if="field.fieldType == 'number'"> {{ 'ERROR_NOT_A_NUMBER' | translate }} </span>
<span ng-if="field.fieldType == 'link'"> {{ 'ERROR_URL_INVALID' | translate }} </span>
</div>
</div>
@ -49,7 +48,7 @@
<div>
<div class="btn btn-lg btn-default col-xs-12 col-sm-4 hidden-xs"
style="padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)">
<button ng-disabled="!field.fieldValue || forms.myForm.{{field.fieldType}}{{$index}}.$invalid"
<button ng-disabled="!field.fieldValue || field.$invalid"
ng-style="{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}"
ng-click="nextField()"
class="btn col-sm-5 col-xs-5">

View file

@ -1,7 +1,9 @@
<div class="field row radio"
ng-click="setActiveField(field._id, index, true)"
on-tab-and-shift-key="prevField()"
key-to-truthy key-char-truthy="y" key-char-falsey="n" field="field">
key-to-truthy key-char-truthy="y" key-char-falsey="n" field="field"
on-valid-key="nextField()"
ng-show="!field.disabled">
<div class="col-xs-12 field-title" ng-style="{'color': design.colors.questionColor}">
<h3 class="row">
<small class="field-number">
@ -26,11 +28,9 @@
class="focusOn"
style="opacity: 0; margin-left: 0px;"
ng-model="field.fieldValue"
ng-focus="setActiveField(field._id, index, true)"
ng-model-options="{ debounce: 250 }"
ng-required="field.required"
ng-change="$root.nextField()"
ng-disabled="field.disabled" />
ng-change="nextField()"/>
<div class="letter">
{{ 'Y' | translate }}
</div>
@ -48,14 +48,12 @@
ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }"
ng-required="field.required"
ng-change="$root.nextField()"
ng-disabled="field.disabled"/>
<div class="letter">
{{ 'N' | translate }}
</div>
<span>{{ 'NO' | translate }}</span>
<i ng-show="field.fieldValue === 'false'" class="fa fa-check" aria-hidden="true"></i>
ng-change="nextField()"/>
<div class="letter">
{{ 'N' | translate }}
</div>
<span>{{ 'NO' | translate }}</span>
<i ng-show="field.fieldValue === 'false'" class="fa fa-check" aria-hidden="true"></i>
</label>
</div>
</div>

View file

@ -4,24 +4,31 @@ angular.module('view-form').directive('keyToTruthy', ['$rootScope', function($ro
return {
restrict: 'A',
scope: {
field: '='
field: '=',
nextField: '&'
},
link: function($scope, $element, $attrs) {
$element.bind('keydown keypress', function(event) {
var keyCode = event.which || event.keyCode;
var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32;
var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32;
if(keyCode === truthyKeyCode ) {
console.log($scope);
if(keyCode === truthyKeyCode ) {
event.preventDefault();
$scope.$apply(function() {
$scope.field.fieldValue = 'true';
if($attrs.onValidKey){
$scope.$root.$eval($attrs.onValidKey);
}
});
}else if(keyCode === falseyKeyCode){
event.preventDefault();
$scope.$apply(function() {
$scope.field.fieldValue = 'false';
});
if($attrs.onValidKey){
$scope.$root.$eval($attrs.onValidKey);
}
});
}
});
}

View file

@ -19,16 +19,13 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
//Setup UI-Sortable
$scope.sortableOptions = {
appendTo: '.dropzone',
helper: 'clone',
//helper: 'clone',
forceHelperSize: true,
forcePlaceholderSize: true,
update: function(e, ui) {
$scope.update(false, $scope.myform, false, false, function(err){
if(!err) $scope.myform.form_fields.push(newField);
$scope.update(false, $scope.myform, false, false, function(err){
});
},
start: function(e, ui) {
}
};
/*
@ -294,10 +291,10 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
if(fieldType === 'rating'){
newField.ratingOptions = {
steps: 1,
steps: 5,
shape: 'Heart'
};
newField.fieldValue = '0';
newField.fieldValue = 0;
}
if($scope.showAddOptions(newField)){

View file

@ -13,16 +13,32 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
$scope.table = {
masterChecker: false,
rows: $scope.myform.submissions
rows: []
};
var submissions = $scope.myform.submissions || [];
//Iterate through form's submissions
for(var i = 0; i < submissions.length; i++){
for(var x = 0; x < submissions[i].form_fields.length; x++){
if(submissions[i].form_fields[x].fieldType === 'dropdown'){
submissions[i].form_fields[x].fieldValue = submissions[i].form_fields[x].fieldValue.option_value;
}
//var oldValue = submissions[i].form_fields[x].fieldValue || '';
//submissions[i].form_fields[x] = _.merge(defaultFormFields, submissions[i].form_fields);
//submissions[i].form_fields[x].fieldValue = oldValue;
}
submissions[i].selected = false;
}
$scope.table.rows = submissions;
var initController = function(){
Forms.get({
formId: $stateParams.formId
}, function(form){
$scope.myform = form;
$scope.table.rows = form.submissions;
/*var defaultFormFields = _.cloneDeep($scope.myform.form_fields);
var defaultFormFields = _.cloneDeep($scope.myform.form_fields);
var submissions = $scope.myform.submissions || [];
@ -39,7 +55,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
submissions[i].selected = false;
}
$scope.table.rows = submissions;*/
$scope.table.rows = submissions;
});
};

View file

@ -67,7 +67,56 @@
<uib-tab ng-repeat="tab in tabData" index="{{$index+1}}" heading="{{tab.heading}}">
<div class='row' data-ng-include="'/static/modules/forms/admin/views/adminTabs/'+tab.templateName+'.html'" onload="form_url = trustSrc(formURL)"></div>
</uib-tab>
<uib-tab ng-if="tabData && myform.form_fields.length" heading="{{ 'DESIGN_TAB' | translate }}" index="{{tabData.length+1}}">
<uib-tab index="2" heading="{{ 'ANALYZE_TAB' | translate }}">
<edit-submissions-form-directive myform="myform" user="myform.admin"></edit-submissions-form-directive>
</uib-tab>
<uib-tab ng-if="tabData" heading="{{ 'SHARE_TAB' | translate }}" index="{{tabData.length}}">
<div class="config-form">
<div class="row">
<div class="col-sm-12">
<uib-tabset active="activePill" vertical="true" type="pills">
<uib-tab index="0" heading="{{ 'SHARE_YOUR_FORM' | translate }}">
<div class="row">
<div class="col-sm-12">
{{ 'TELLFORM_URL' | translate }}
</div>
<div class="col-sm-8 form-input">
<span ngclipboard data-clipboard-target="#copyURL"> <input id="copyURL" ng-value="actualFormURL" class="form-control ng-pristine ng-untouched ng-valid"> </span>
</div>
<div class="col-sm-4">
<button class="btn btn btn-secondary view-form-btn" ngclipboard data-clipboard-target="#copyURL">
{{ 'COPY' | translate }} <i class="fa fa-clipboard" aria-hidden="true"></i>
</button>
</div>
</div>
</uib-tab>
<uib-tab index="1" heading="{{ 'EMBED_YOUR_FORM' | translate }}">
<div class="row">
<div class="col-sm-12">
{{ 'COPY_AND_PASTE' | translate }}
</div>
<div class="col-sm-8 form-input">
<span ngclipboard data-clipboard-target="#copyEmbedded">
<textarea id="copyEmbedded" class="form-control ng-pristine ng-untouched ng-valid" style="min-height:200px; width:100%; background-color: #FFFFCC; color: #30313F;">
&lt;!-- {{ 'CHANGE_WIDTH_AND_HEIGHT' | translate }} --&gt;
<iframe id="iframe" src="{{actualFormURL}}" style="width:100%;height:500px;"></iframe>
<div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5; padding-top: 5px;">{{ 'POWERED_BY' | translate }} <a href="https://www.tellform.com" style="color: #999" target="_blank">TellForm</a></div>
</textarea>
</span>
</div>
<div class="col-sm-4">
<button class="btn btn btn-secondary view-form-btn" ngclipboard data-clipboard-target="#copyEmbedded">
{{ 'COPY' | translate }} <i class="fa fa-clipboard" aria-hidden="true"></i>
</button>
</div>
</div>
</uib-tab>
</uib-tabset>
</div>
</div>
</div>
</uib-tab>
<uib-tab ng-if="tabData && myform.form_fields.length" heading="{{ 'DESIGN_TAB' | translate }}" index="{{tabData.length}}+1">
<div class="config-form design container">
<div class="row">
<div class="col-md-4 col-sm-12 container">

View file

@ -556,7 +556,7 @@
<div class="row">
<div class="col-sm-12 col-md-10 dropzoneContainer">
<div class="panel-group dropzone" ui-sortable="sortableOptions">
<div class="panel-group dropzone" ui-sortable="sortableOptions" ng-model="myform.form_fields">
<div class="panel panel-default" ng-repeat="field in myform.form_fields"
ng-if="!field.deletePreserved"

View file

@ -26,7 +26,7 @@
<div class="col-xs-offset-3 col-xs-6 col-sm-offset-4 col-sm-4">
<form name="userForm" data-ng-submit="signup()" class="signin form-horizontal" autocomplete="off">
<fieldset>
<div data-ng-show="error" id="signup_errors" class="text-center text-danger">
<div data-ng-show="error" id="signup_errors" class="text-center">
{{'SIGNUP_ERROR_TEXT' | translate}}: <br>
<strong data-ng-bind="error"></strong>
</div>