fixed bug in form controller

This commit is contained in:
David Baldwynn 2017-10-07 00:27:03 -07:00
parent 3cc99d7b17
commit 3ebb4eebff
22 changed files with 304 additions and 234 deletions

View File

@ -164,7 +164,7 @@ var readForRender = exports.readForRender = function(req, res) {
delete newForm.__v; delete newForm.__v;
delete newForm.created; delete newForm.created;
if(!newForm.startPage.showStart){ if(newForm.startPage && !newForm.startPage.showStart){
delete newForm.startPage; delete newForm.startPage;
} }
@ -175,20 +175,31 @@ var readForRender = exports.readForRender = function(req, res) {
* Update a form * Update a form
*/ */
exports.update = function(req, res) { exports.update = function(req, res) {
var form = req.form; var form = req.form;
var updatedForm = req.body.form; var updatedForm = req.body.form;
if(form.form_fields === undefined){
form.form_fields = [];
}
delete updatedForm.__v; if(form.analytics === undefined){
delete updatedForm.created; form.analytics = {
visitors: [],
gaCode: ''
}
}
if (req.body.changes) { if (req.body.changes) {
var formChanges = req.body.changes; var formChanges = req.body.changes;
formChanges.forEach(function (change) { formChanges.forEach(function (change) {
diff.applyChange(form, true, change); diff.applyChange(form._doc, true, change);
}); });
} else { } else {
//Unless we have 'admin' privileges, updating form admin is disabled
delete updatedForm.__v;
delete updatedForm.created;
//Unless we have 'admin' privileges, updating the form's admin is disabled
if(updatedForm && req.user.roles.indexOf('admin') === -1) { if(updatedForm && req.user.roles.indexOf('admin') === -1) {
delete updatedForm.admin; delete updatedForm.admin;
} }
@ -200,7 +211,7 @@ exports.update = function(req, res) {
//Do this so we can create duplicate fields //Do this so we can create duplicate fields
var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$'); var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$');
for(var i=0; i<req.body.form.form_fields.length; i++){ for(var i=0; i < req.body.form.form_fields.length; i++){
var field = req.body.form.form_fields[i]; var field = req.body.form.form_fields[i];
if(!checkForValidId.exec(field._id+'')){ if(!checkForValidId.exec(field._id+'')){
delete field._id; delete field._id;

View File

@ -76,8 +76,7 @@ function BaseFieldSchema(){
}, },
title: { title: {
type: String, type: String,
trim: true, trim: true
required: 'Field Title cannot be blank'
}, },
description: { description: {
type: String, type: String,
@ -106,7 +105,6 @@ function BaseFieldSchema(){
}, },
fieldType: { fieldType: {
type: String, type: String,
required: true,
enum: [ enum: [
'textfield', 'textfield',
'date', 'date',

View File

@ -76,11 +76,6 @@
<script src="/static/lib/jquery/dist/jquery.min.js" type="text/javascript"></script> <script src="/static/lib/jquery/dist/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(window).on("load", function() {
$(".loader").fadeOut("slow");
});
</script>
<link rel="stylesheet" href="/static/lib/font-awesome/css/font-awesome.min.css"> <link rel="stylesheet" href="/static/lib/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="/static/lib/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/lib/bootstrap/dist/css/bootstrap.min.css">

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,7 @@ angular.module('view-form').controller('SubmitFormController', [
function($scope, $rootScope, $state, $translate, myForm) { function($scope, $rootScope, $state, $translate, myForm) {
$scope.myform = myForm; $scope.myform = myForm;
$(".loader").fadeOut("slow");
document.body.style.background = myForm.design.colors.backgroundColor; document.body.style.background = myForm.design.colors.backgroundColor;
$translate.use(myForm.language); $translate.use(myForm.language);
} }

View File

@ -25,7 +25,7 @@ angular.module('view-form').directive('onEnterKey', ['$rootScope', function($roo
return { return {
restrict: 'A', restrict: 'A',
link: function($scope, $element, $attrs) { link: function($scope, $element, $attrs) {
$element.bind('keydown keypress', function(event) { $element.bind('keyup keypress', function(event) {
var keyCode = event.which || event.keyCode; var keyCode = event.which || event.keyCode;
@ -65,6 +65,8 @@ angular.module('view-form').directive('onEnterKey', ['$rootScope', function($roo
var keyCode = event.which || event.keyCode; var keyCode = event.which || event.keyCode;
if(keyCode === 9 && event.shiftKey) { if(keyCode === 9 && event.shiftKey) {
console.log('onTabAndShiftKey');
event.preventDefault(); event.preventDefault();
$rootScope.$apply(function() { $rootScope.$apply(function() {
$rootScope.$eval($attrs.onTabAndShiftKey); $rootScope.$eval($attrs.onTabAndShiftKey);

View File

@ -9,8 +9,8 @@ jsep.addBinaryOp('!begins', 10);
jsep.addBinaryOp('ends', 10); jsep.addBinaryOp('ends', 10);
jsep.addBinaryOp('!ends', 10); jsep.addBinaryOp('!ends', 10);
angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', '$translate', angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', '$translate', '$timeout',
function ($http, TimeCounter, $filter, $rootScope, SendVisitorData, $translate) { function ($http, TimeCounter, $filter, $rootScope, SendVisitorData, $translate, $timeout) {
return { return {
templateUrl: 'form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html', templateUrl: 'form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html',
restrict: 'E', restrict: 'E',
@ -19,7 +19,8 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
ispreview: '=' ispreview: '='
}, },
controller: function($document, $window, $scope){ controller: function($document, $window, $scope){
$scope.noscroll = false; var NOSCROLL = false;
var FORM_ACTION_ID = 'submit_field';
$scope.forms = {}; $scope.forms = {};
//Don't start timer if we are looking at a design preview //Don't start timer if we are looking at a design preview
@ -59,43 +60,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
TimeCounter.restartClock(); TimeCounter.restartClock();
}; };
//Fire event when window is scrolled
$window.onscroll = function(){
$scope.scrollPos = document.body.scrollTop || document.documentElement.scrollTop || 0;
var elemBox = document.getElementsByClassName('activeField')[0].getBoundingClientRect();
$scope.fieldTop = elemBox.top;
$scope.fieldBottom = elemBox.bottom;
var field_id;
var field_index;
if(!$scope.noscroll){
//Focus on submit button
if( $scope.selected.index === $scope.myform.visible_form_fields.length-1 && $scope.fieldBottom < 200){
field_index = $scope.selected.index+1;
field_id = 'submit_field';
$scope.setActiveField(field_id, field_index, false);
}
//Focus on field above submit button
else if($scope.selected.index === $scope.myform.visible_form_fields.length){
if($scope.fieldTop > 200){
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.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) {
field_index = $scope.selected.index-1;
field_id = $scope.myform.visible_form_fields[field_index]._id;
$scope.setActiveField(field_id, field_index, false);
}
$scope.$apply();
}
};
/* /*
** Field Controls ** Field Controls
*/ */
@ -163,35 +127,46 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
throw new Error('current active field is null'); throw new Error('current active field is null');
} }
if($scope.selected._id === 'submit_field') { if($scope.selected._id === FORM_ACTION_ID) {
return $scope.myform.form_fields.length - 1; return $scope.myform.form_fields.length - 1;
} }
return $scope.selected.index; return $scope.selected.index;
};
$scope.isActiveField = function(field){
if($scope.selected._id === field._id) {
return true
}
return false;
}; };
$scope.setActiveField = $rootScope.setActiveField = function(field_id, field_index, animateScroll) { $scope.setActiveField = $rootScope.setActiveField = function(field_id, field_index, animateScroll) {
if($scope.selected === null || $scope.selected._id === field_id){ if($scope.selected === null || (!field_id && field_index === null) ) {
//console.log('not scrolling'); return;
//console.log($scope.selected); }
return;
} if(!field_id){
//console.log('field_id: '+field_id); field_id = $scope.myform.visible_form_fields[field_index]._id;
//console.log('field_index: '+field_index); } else if(field_index === null){
//console.log($scope.selected); field_index = $scope.myform.visible_form_fields.length
$scope.selected._id = field_id; for(var i=0; i < $scope.myform.visible_form_fields.length; i++){
$scope.selected.index = field_index;
if(!field_index){
for(var i=0; i<$scope.myform.visible_form_fields.length; i++){
var currField = $scope.myform.visible_form_fields[i]; var currField = $scope.myform.visible_form_fields[i];
if(field_id === currField._id){ if(currField['_id'] == field_id){
$scope.selected.index = i; field_index = i;
break; break;
} }
} }
} }
if($scope.selected._id === field_id){
return;
}
$scope.selected._id = field_id;
$scope.selected.index = field_index;
var nb_valid = $filter('formValidity')($scope.myform); var nb_valid = $filter('formValidity')($scope.myform);
$scope.translateAdvancementData = { $scope.translateAdvancementData = {
done: nb_valid, done: nb_valid,
@ -200,10 +175,10 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
}; };
if(animateScroll){ if(animateScroll){
$scope.noscroll=true; NOSCROLL=true;
setTimeout(function() { setTimeout(function() {
$document.scrollToElement(angular.element('.activeField'), -10, 200).then(function() { $document.scrollToElement(angular.element('.activeField'), -10, 200).then(function() {
$scope.noscroll = false; NOSCROLL = false;
setTimeout(function() { setTimeout(function() {
if (document.querySelectorAll('.activeField .focusOn').length) { if (document.querySelectorAll('.activeField .focusOn').length) {
//Handle default case //Handle default case
@ -218,54 +193,99 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
}); });
}); });
}); });
} else { }
setTimeout(function() {
if (document.querySelectorAll('.activeField .focusOn')[0]) {
//FIXME: DAVID: Figure out how to set focus without scroll movement in HTML Dom
document.querySelectorAll('.activeField .focusOn')[0].focus();
} else if (document.querySelectorAll('.activeField input')[0]){
document.querySelectorAll('.activeField input')[0].focus();
}
});
}
//Only send analytics data if form has not been submitted
if(!$scope.myform.submitted){
SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed());
}
}; };
//Fire event when window is scrolled
$window.onscroll = function(){
if(!NOSCROLL){
var scrollTop = $(window).scrollTop();
var elemBox = document.getElementsByClassName('activeField')[0].getBoundingClientRect();
var fieldTop = elemBox.top;
var fieldBottom = elemBox.bottom;
var field_id, field_index;
var elemHeight = $('.activeField').height();
var submitSectionHeight = $('.form-actions').height();
var maxScrollTop = $(document).height() - $(window).height();
var fieldWrapperHeight = $('form_fields').height();
var selector = 'form > .field-directive:nth-of-type(' + String($scope.myform.visible_form_fields.length - 1)+ ')'
var fieldDirectiveHeight = $(selector).height()
var scrollPosition = maxScrollTop - submitSectionHeight - fieldDirectiveHeight*1.2;
var fractionToJump = 0.9;
//Focus on field above submit form button
if($scope.selected.index === $scope.myform.visible_form_fields.length){
if(scrollTop < scrollPosition){
field_index = $scope.selected.index-1;
$scope.setActiveField(null, field_index, false);
}
}
//Focus on submit form button
else if($scope.selected.index === $scope.myform.visible_form_fields.length-1 && scrollTop > scrollPosition){
field_index = $scope.selected.index+1;
$scope.setActiveField(FORM_ACTION_ID, field_index, false);
}
//If we scrolled bellow the current field, move to next field
else if(fieldBottom < elemHeight * fractionToJump && $scope.selected.index < $scope.myform.visible_form_fields.length-1 ){
field_index = $scope.selected.index+1;
$scope.setActiveField(null, field_index, false);
}
//If we scrolled above the current field, move to prev field
else if ( $scope.selected.index !== 0 && fieldTop > elemHeight * fractionToJump) {
field_index = $scope.selected.index-1;
$scope.setActiveField(null, field_index, false);
}
}
$scope.$apply();
};
$rootScope.nextField = $scope.nextField = function(){ $rootScope.nextField = $scope.nextField = function(){
var currField = $scope.myform.visible_form_fields[$scope.selected.index];
if($scope.selected && $scope.selected.index > -1){ if($scope.selected && $scope.selected.index > -1){
//Jump to logicJump's destination if it is true
if(currField.logicJump && evaluateLogicJump(currField)){
$rootScope.setActiveField(currField.logicJump.jumpTo, null, true);
} else {
var selected_index, selected_id;
if($scope.selected.index < $scope.myform.visible_form_fields.length-1){
selected_index = $scope.selected.index+1;
selected_id = $scope.myform.visible_form_fields[selected_index]._id;
$rootScope.setActiveField(selected_id, selected_index, true);
} else if($scope.selected.index === $scope.myform.visible_form_fields.length-1) {
selected_index = $scope.selected.index+1;
selected_id = 'submit_field';
$rootScope.setActiveField(selected_id, selected_index, true);
}
}
}
if($scope.selected._id !== FORM_ACTION_ID){
var currField = $scope.myform.visible_form_fields[$scope.selected.index];
//Jump to logicJump's destination if it is true
if(currField.logicJump && currField.logicJump.jumpTo && evaluateLogicJump(currField)){
$scope.setActiveField(currField.logicJump.jumpTo, null, true);
} else if($scope.selected.index < $scope.myform.visible_form_fields.length-1){
$scope.setActiveField(null, $scope.selected.index+1, true);
} else {
$scope.setActiveField(FORM_ACTION_ID, null, true);
}
} else {
//If we are at the submit actions page, go to the first field
$rootScope.setActiveField(null, 0, true);
}
} else {
//If selected is not defined go to the first field
$rootScope.setActiveField(null, 0, true);
}
}; };
$rootScope.prevField = $scope.prevField = function(){ $rootScope.prevField = $scope.prevField = function(){
console.log('prevField');
console.log($scope.selected);
var selected_index = $scope.selected.index - 1;
if($scope.selected.index > 0){ if($scope.selected.index > 0){
var selected_index = $scope.selected.index - 1; $scope.setActiveField(null, selected_index, true);
var selected_id = $scope.myform.visible_form_fields[selected_index]._id;
$scope.setActiveField(selected_id, selected_index, true);
} }
}; };
$rootScope.goToInvalid = $scope.goToInvalid = function() {
var field_id = $('.row.field-directive .ng-invalid.focusOn, .row.field-directive .ng-untouched.focusOn:not(.ng-valid)').first().parents('.row.field-directive').first().attr('data-id');
$scope.setActiveField(field_id, null, true);
};
/* /*
** Form Display Functions ** Form Display Functions
*/ */
@ -276,10 +296,6 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
} }
}; };
$rootScope.goToInvalid = $scope.goToInvalid = function() {
document.querySelectorAll('.ng-invalid.focusOn')[0].focus();
};
var getDeviceData = function(){ var getDeviceData = function(){
var md = new MobileDetect(window.navigator.userAgent); var md = new MobileDetect(window.navigator.userAgent);
var deviceType = 'other'; var deviceType = 'other';
@ -320,6 +336,10 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
}; };
$rootScope.submitForm = $scope.submitForm = function() { $rootScope.submitForm = $scope.submitForm = function() {
if($scope.forms.myForm.$invalid){
$scope.goToInvalid();
return;
}
var _timeElapsed = TimeCounter.stopClock(); var _timeElapsed = TimeCounter.stopClock();
$scope.loading = true; $scope.loading = true;

View File

@ -16,6 +16,7 @@
<div class="col-xs-12 field-input"> <div class="col-xs-12 field-input">
<div class="control-group input-append"> <div class="control-group input-append">
<input class="focusOn" <input class="focusOn"
ng-focus="setActiveField(field._id, null, false)"
ng-style="{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}" ng-style="{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}"
ng-class="{ 'no-border': !!field.fieldValue }" ng-class="{ 'no-border': !!field.fieldValue }"
ui-date="dateOptions" ui-date="dateOptions"

View File

@ -15,6 +15,7 @@
</div> </div>
<div class="col-xs-12 field-input"> <div class="col-xs-12 field-input">
<ui-select ng-model="field.fieldValue" <ui-select ng-model="field.fieldValue"
ng-focus="setActiveField(field._id, null, false)"
theme="selectize" theme="selectize"
search-enabled="true" search-enabled="true"
search-by="option_value" search-by="option_value"

View File

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

View File

@ -12,7 +12,7 @@
<p class="col-xs-12" ng-if="field.description.length">{{field.description}} </p> <p class="col-xs-12" ng-if="field.description.length">{{field.description}} </p>
<br> <br>
<div class="col-xs-offset-1 col-xs-11"> <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-style="{'font-size': '1.3em', 'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}"
ng-click="nextField()"> ng-click="nextField()">
{{ 'CONTINUE' | translate }} {{ 'CONTINUE' | translate }}

View File

@ -16,6 +16,7 @@
<div class="col-xs-12 field-input"> <div class="col-xs-12 field-input">
<small style="font-size:0.6em;">Press SHIFT+ENTER to add a newline</small> <small style="font-size:0.6em;">Press SHIFT+ENTER to add a newline</small>
<textarea class="textarea focusOn" type="text" <textarea class="textarea focusOn" type="text"
ng-focus="setActiveField(field._id, null, false)"
ng-model="field.fieldValue" ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }" ng-model-options="{ debounce: 250 }"
ng-class="{ 'no-border': !!field.fieldValue }" ng-class="{ 'no-border': !!field.fieldValue }"

View File

@ -26,6 +26,7 @@
placeholder="{{placeholder}}" placeholder="{{placeholder}}"
ng-class="{ 'no-border': !!field.fieldValue }" ng-class="{ 'no-border': !!field.fieldValue }"
class="focusOn text-field-input" class="focusOn text-field-input"
ng-focus="setActiveField(field._id, null, false)"
ng-model="field.fieldValue" ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }" ng-model-options="{ debounce: 250 }"
value="field.fieldValue" value="field.fieldValue"
@ -45,7 +46,7 @@
</div> </div>
</div> </div>
<div> <div>
<div class="btn btn-lg btn-default" <div class="btn btn-lg btn-default" ng-disabled="!field.fieldValue || field.$invalid"
style="padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)"> style="padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)">
<button ng-disabled="!field.fieldValue || field.$invalid" <button ng-disabled="!field.fieldValue || field.$invalid"
ng-style="{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}" ng-style="{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}"

View File

@ -28,6 +28,7 @@
<input type="radio" value="true" <input type="radio" value="true"
class="focusOn" class="focusOn"
style="opacity: 0; margin-left: 0px;" style="opacity: 0; margin-left: 0px;"
ng-focus="setActiveField(field._id, null, false)"
ng-model="field.fieldValue" ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }" ng-model-options="{ debounce: 250 }"
ng-required="field.required" ng-required="field.required"
@ -46,6 +47,7 @@
<input type="radio" value="false" <input type="radio" value="false"
style="opacity:0; margin-left:0px;" style="opacity:0; margin-left:0px;"
ng-focus="setActiveField(field._id, null, false)"
ng-model="field.fieldValue" ng-model="field.fieldValue"
ng-model-options="{ debounce: 250 }" ng-model-options="{ debounce: 250 }"
ng-required="field.required" ng-required="field.required"

View File

@ -1,16 +1,13 @@
<section class="overlay submitform" ng-if="!ispreview && (loading || (!myform.submitted && !myform.startPage.showStart))"></section>
<section class="overlay previewform submitform" ng-if="ispreview && (loading || (!myform.submitted && !myform.startPage.showStart))"></section>
<!-- Start Page View --> <!-- Start Page View -->
<div ng-show="!myform.submitted && myform.startPage.showStart" class="form-submitted" style="padding-top: 35vh;"> <div ng-show="!myform.submitted && myform.startPage.showStart" class="form-submitted" style="padding-top: 35vh;">
<div class="row"> <div class="row">
<div class="col-xs-12 text-center" style="overflow-wrap: break-word;"> <div class="col-xs-12 text-center" style="overflow-wrap: break-word;">
<h1 style="font-weight: 400; nont-size: 25px;" ng-style="{'color': form.design.colors.questionColor}"> <h1 style="font-weight: 400; nont-size: 25px;" ng-style="{'color': myform.design.colors.questionColor}">
{{myform.startPage.introTitle}} {{myform.startPage.introTitle}}
</h1> </h1>
</div> </div>
<div class="col-xs-10 col-xs-offset-1 text-center" style="overflow-wrap: break-word;"> <div class="col-xs-10 col-xs-offset-1 text-center" style="overflow-wrap: break-word;">
<p style="font-weight: 100; font-size: 16px;" ng-style="{'color': form.design.colors.questionColor}"> <p style="font-weight: 100; font-size: 16px;" ng-style="{'color': myform.design.colors.questionColor}">
{{myform.startPage.introParagraph}} {{myform.startPage.introParagraph}}
</p> </p>
</div> </div>
@ -37,42 +34,46 @@
</div> </div>
<!-- Form Fields View --> <!-- Form Fields View -->
<div class="form-fields" ng-show="!myform.submitted && !myform.startPage.showStart" ng-style="{ 'border-color': myform.design.colors.buttonTextColor }"> <div class="form-fields"
ng-show="!myform.submitted && !myform.startPage.showStart"
ng-style="{ 'border-color': myform.design.colors.buttonTextColor }">
<div class="row"> <div class="row form-field-wrapper">
<form name="forms.myForm" novalidate class="submission-form col-sm-12 col-md-offset-1 col-md-10"> <form name="forms.myForm" novalidate class="submission-form">
<div ng-repeat="field in myform.form_fields" ng-if="!field.deletePreserved" data-index="{{$index}}" data-id="{{field._id}}" ng-class="{activeField: selected._id == field._id }" class="row field-directive"> <div ng-repeat="field in myform.form_fields" ng-if="!field.deletePreserved" data-index="{{$index}}" data-id="{{field._id}}" ng-class="{activeField: selected._id == field._id }" class="row field-directive">
<field-directive field="field" design="myform.design" index="$index" forms="forms"> <field-directive field="field" design="myform.design" index="$index" forms="forms">
</field-directive> </field-directive>
</div> </div>
<div class="row form-actions" id="submit_field" ng-class="{activeField: selected._id == 'submit_field' }"
ng-style="{ 'background-color':myform.design.colors.buttonColor}" style="border-top: 1px solid #ddd; margin-top: 30vh; height: 100vh; margin-left: 1%; margin-right: 1%;"
on-tab-and-shift-key="prevField()"
on-tab-key="nextField()"
on-enter-key="submitForm()">
<div class="col-xs-12 text-left" style="background-color:#990000; color:white;" ng-if="forms.myForm.$invalid">
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
</div>
<button ng-if="!forms.myForm.$invalid" class="Button btn col-sm-2 col-xs-8 focusOn" v-busy="loading" v-busy-label="Please wait" v-pressable ng-disabled="loading || forms.myForm.$invalid" ng-click="submitForm()" on-enter-key-disabled="loading || forms.myForm.$invalid" ng-style="{'background-color':myform.design.colors.buttonColor, 'color':myform.design.colors.buttonTextColor}" style="font-size: 1.6em; margin-left: 1em; margin-top: 1em;">
{{ 'SUBMIT' | translate }}
</button>
<button ng-if="forms.myForm.$invalid" class="Button btn col-sm-2 col-xs-8 focusOn" ng-click="goToInvalid()" on-enter-key="goToInvalid()" on-enter-key-disabled="!forms.myForm.$invalid" style="font-size: 1.6em; margin-left: 1em; margin-top: 1em; background-color:#990000; color:white">
{{ 'REVIEW' | translate }}
</button>
<div class="col-sm-2 hidden-xs" style="font-size: 75%; margin-top:3.25em">
<small>
{{ 'ENTER' | translate }}
</small>
</div>
</div>
</form> </form>
</div> </div>
<div class="row form-actions" id="submit_field" ng-class="{activeField: selected._id == 'submit_field' }" ng-style="{ 'background-color':myform.design.colors.buttonColor}" style="border-top: 1px solid #ddd; margin-right: -13%; margin-left: -13%; margin-top: 30vh; height: 100vh">
<div class="col-xs-12 text-left" style="background-color:#990000; color:white;" ng-if="forms.myForm.$invalid">
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
</div>
<button ng-if="!forms.myForm.$invalid" class="Button btn col-sm-2 col-xs-8 focusOn" v-busy="loading" v-busy-label="Please wait" v-pressable ng-disabled="loading || forms.myForm.$invalid" ng-click="submitForm()" on-enter-key="submitForm()" on-enter-key-disabled="loading || forms.myForm.$invalid" ng-style="{'background-color':myform.design.colors.buttonColor, 'color':myform.design.colors.buttonTextColor}" style="font-size: 1.6em; margin-left: 1em; margin-top: 1em;">
{{ 'SUBMIT' | translate }}
</button>
<button ng-if="forms.myForm.$invalid" class="Button btn col-sm-2 col-xs-8 focusOn" ng-click="goToInvalid()" on-enter-key="goToInvalid()" on-enter-key-disabled="!forms.myForm.$invalid" style="font-size: 1.6em; margin-left: 1em; margin-top: 1em; background-color:#990000; color:white">
{{ 'REVIEW' | translate }}
</button>
<div class="col-sm-2 hidden-xs" style="font-size: 75%; margin-top:3.25em">
<small>
{{ 'ENTER' | translate }}
</small>
</div>
</div>
<section ng-if="!myform.hideFooter" class="navbar navbar-fixed-bottom" ng-style="{ 'background-color':myform.design.colors.buttonColor, 'padding-top': '15px', 'border-top': '2px '+ myform.design.colors.buttonTextColor +' solid', 'color':myform.design.colors.buttonTextColor}"> <section ng-if="!myform.hideFooter" class="navbar navbar-fixed-bottom" ng-style="{ 'background-color':myform.design.colors.buttonColor, 'padding-top': '15px', 'border-top': '2px '+ myform.design.colors.buttonTextColor +' solid', 'color':myform.design.colors.buttonTextColor}">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">

View File

@ -0,0 +1,12 @@
<script>
$(".loader").fadeOut("slow");
</script>
<section class="public-form auth sigin-view valign-wrapper">
<div class="row valign">
<h3 class="col-md-12 text-center">404 - Form Does not Exist </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 does not exist. Sorry about that!
</div>
</div>
</section>

View File

@ -1,4 +1,7 @@
<section class="auth sigin-view valign-wrapper"> <script>
$(".loader").fadeOut("slow");
</script>
<section class="public-form auth sigin-view valign-wrapper">
<div class="row valign"> <div class="row valign">
<h3 class="col-md-12 text-center">Not Authorized to Access Form</h3> <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-4 col-md-offset-4">

View File

@ -27,7 +27,11 @@ angular.module('view-form').config(['$stateProvider',
}). }).
state('unauthorizedFormAccess', { state('unauthorizedFormAccess', {
url: '/forms/unauthorized', url: '/forms/unauthorized',
templateUrl: '/static/form_modules/forms/base/views/form-unauthorized.client.view.html', templateUrl: '/static/form_modules/forms/base/views/form-unauthorized.client.view.html'
})
.state('formNotFound', {
url: '*path',
templateUrl: '/static/form_modules/forms/base/views/form-not-found.client.view.html'
}); });
} }
]); ]);

View File

@ -16,6 +16,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$scope.animationsEnabled = true; $scope.animationsEnabled = true;
$scope.myform = myForm; $scope.myform = myForm;
$rootScope.saveInProgress = false; $rootScope.saveInProgress = false;
$scope.oldForm = _.cloneDeep($scope.myform);
CurrentForm.setForm($scope.myform); CurrentForm.setForm($scope.myform);
@ -42,13 +43,23 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
} }
}; };
$scope.tabData = [ $scope.tabData = [
{ {
heading: $filter('translate')('CONFIGURE_TAB'), heading: $filter('translate')('CONFIGURE_TAB'),
templateName: 'configure' templateName: 'configure'
} }
]; ];
$scope.designTabActive = false
$scope.deactivateDesignTab = function(){
$scope.designTabActive = false
}
$scope.activateDesignTab = function(){
$scope.designTabActive = true
}
$scope.setForm = function(form){ $scope.setForm = function(form){
$scope.myform = form; $scope.myform = form;
}; };
@ -102,16 +113,20 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
} }
}; };
// Update existing Form $scope.updateDesign = function(updateImmediately, data, shouldDiff, refreshAfterUpdate){
$scope.update = $rootScope.update = function(updateImmediately, data, isDiffed, refreshAfterUpdate, cb){ $scope.update(updateImmediately, data, shouldDiff, refreshAfterUpdate, function(){
refreshFrame(); refreshFrame();
});
}
// Update existing Form
$scope.update = $rootScope.update = function(updateImmediately, data, shouldDiff, refreshAfterUpdate, cb){
var continueUpdate = true; var continueUpdate = true;
if(!updateImmediately){ if(!updateImmediately){
continueUpdate = !$rootScope.saveInProgress; continueUpdate = !$rootScope.saveInProgress;
} }
//Update form **if we are not currently updating** or if **shouldUpdateNow flag is set** //Update form **if we are not in the middle of an update** or if **shouldUpdateNow flag is set**
if(continueUpdate) { if(continueUpdate) {
var err = null; var err = null;
@ -119,11 +134,24 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
$rootScope.saveInProgress = true; $rootScope.saveInProgress = true;
} }
if (isDiffed) { if (shouldDiff) {
//Do this so we can create duplicate fields
var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$');
for(var i=0; i < $scope.myform.form_fields.length; i++){
var field = $scope.myform.form_fields[i];
if(!checkForValidId.exec(field._id+'')){
delete $scope.myform.form_fields[i]._id;
delete $scope.myform.form_fields[i].id;
}
}
var data = DeepDiff.diff($scope.oldForm, $scope.myform);
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {changes: data}) $scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {changes: data})
.then(function (response) { .then(function (response) {
if (refreshAfterUpdate) { if (refreshAfterUpdate) {
$rootScope.myform = $scope.myform = response.data; $rootScope.myform = $scope.myform = response.data;
$scope.oldForm = _.cloneDeep($scope.myform);
} }
}).catch(function (response) { }).catch(function (response) {
err = response.data; err = response.data;
@ -146,6 +174,22 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$windo
delete dataToSend.submissions; delete dataToSend.submissions;
} }
if(dataToSend.visible_form_fields){
delete dataToSend.visible_form_fields;
}
if(dataToSend.analytics){
delete dataToSend.analytics.visitors;
delete dataToSend.analytics.fields;
delete dataToSend.analytics.submissions;
delete dataToSend.analytics.views;
delete dataToSend.analytics.conversionRate;
}
delete dataToSend.created;
delete dataToSend.lastModified;
delete dataToSend.__v;
$scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {form: dataToSend}) $scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {form: dataToSend})
.then(function (response) { .then(function (response) {
if (refreshAfterUpdate) { if (refreshAfterUpdate) {

View File

@ -1,3 +1,4 @@
'use strict'; 'use strict';
angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormFields', '$uibModal', angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormFields', '$uibModal',
@ -23,7 +24,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
forceHelperSize: true, forceHelperSize: true,
forcePlaceholderSize: true, forcePlaceholderSize: true,
update: function(e, ui) { update: function(e, ui) {
$scope.update(false, $scope.myform, false, false, function(err){ $rootScope.update(false, $scope.myform, true, false, function(err){
}); });
}, },
}; };
@ -129,7 +130,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
$scope.saveField = function(){ $scope.saveField = function(){
$scope.myform.form_fields.push(curr_field); $scope.myform.form_fields.push(curr_field);
$scope.$parent.update(false, $scope.$parent.myform, false, true, function(){ $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){
$uibModalInstance.close(); $uibModalInstance.close();
}); });
}; };
@ -184,7 +185,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
}; };
$scope.saveStartPage = function(){ $scope.saveStartPage = function(){
$scope.$parent.update(false, $scope.$parent.myform, false, true, function(){ $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){
$uibModalInstance.close(); $uibModalInstance.close();
}); });
}; };
@ -196,7 +197,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
}; };
/* /*
** EditStartPageModal Functions ** EditEndPageModal Functions
*/ */
$scope.openEditEndPageModal = function(){ $scope.openEditEndPageModal = function(){
$scope.editEndPageModal = $uibModal.open({ $scope.editEndPageModal = $uibModal.open({
@ -239,7 +240,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
}; };
$scope.saveEndPage = function(){ $scope.saveEndPage = function(){
$scope.$parent.update(false, $scope.$parent.myform, false, true, function(){ $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){
$uibModalInstance.close(); $uibModalInstance.close();
}); });
}; };
@ -335,7 +336,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
// Delete particular field on button click // Delete particular field on button click
$scope.deleteField = function (field_index) { $scope.deleteField = function (field_index) {
$scope.myform.form_fields.splice(field_index, 1); $scope.myform.form_fields.splice(field_index, 1);
$scope.update(false, $scope.myform, false, true, null); $rootScope.update(false, $scope.myform, false, true, null);
}; };
$scope.duplicateField = function(field_index){ $scope.duplicateField = function(field_index){
@ -345,7 +346,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
//Insert field at selected index //Insert field at selected index
$scope.myform.form_fields.push(currField); $scope.myform.form_fields.push(currField);
$scope.update(false, $scope.myform, false, true, null); $rootScope.update(false, $scope.myform, false, true, null);
}; };
//Populate AddField with all available form field types //Populate AddField with all available form field types

View File

@ -59,16 +59,16 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<uib-tabset active="activePill" vertical="true" type="pills"> <uib-tabset active="activePill" vertical="true" type="pills">
<uib-tab index="0" heading="{{ 'CREATE_TAB' | translate }}"> <uib-tab index="0" heading="{{ 'CREATE_TAB' | translate }}" select="deactivateDesignTab()">
<edit-form-directive myform="myform"></edit-form-directive> <edit-form-directive myform="myform"></edit-form-directive>
</uib-tab> </uib-tab>
<uib-tab ng-repeat="tab in tabData" index="{{$index+1}}" heading="{{tab.heading}}"> <uib-tab ng-repeat="tab in tabData" index="{{$index+1}}" heading="{{tab.heading}}" select="deactivateDesignTab()">
<div class='row' data-ng-include="'/static/modules/forms/admin/views/adminTabs/'+tab.templateName+'.html'"></div> <div class='row' data-ng-include="'/static/modules/forms/admin/views/adminTabs/'+tab.templateName+'.html'"></div>
</uib-tab> </uib-tab>
<uib-tab index="2" heading="{{ 'ANALYZE_TAB' | translate }}"> <uib-tab index="2" heading="{{ 'ANALYZE_TAB' | translate }}" select="deactivateDesignTab()">
<edit-submissions-form-directive myform="myform" user="myform.admin"></edit-submissions-form-directive> <edit-submissions-form-directive myform="myform" user="myform.admin"></edit-submissions-form-directive>
</uib-tab> </uib-tab>
<uib-tab ng-if="tabData" heading="{{ 'SHARE_TAB' | translate }}" index="{{tabData.length}}"> <uib-tab ng-if="tabData" heading="{{ 'SHARE_TAB' | translate }}" index="{{tabData.length}}" select="deactivateDesignTab()">
<div class="config-form"> <div class="config-form">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
@ -114,7 +114,8 @@
</div> </div>
</div> </div>
</uib-tab> </uib-tab>
<uib-tab ng-if="tabData && myform.form_fields.length" heading="{{ 'DESIGN_TAB' | translate }}" index="{{tabData.length}}+1"> <uib-tab class="design-tab" ng-if="tabData && myform.form_fields.length" heading="{{ 'DESIGN_TAB' | translate }}" index="{{tabData.length}}+1"
select="activateDesignTab()">
<div class="config-form design container"> <div class="config-form design container">
<div class="row"> <div class="row">
<div class="col-sm-4 col-xs-12"> <div class="col-sm-4 col-xs-12">
@ -175,7 +176,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-8 hidden-xs"> <div class="col-sm-8 hidden-xs" ng-if="designTabActive">
<div class="public-form" ng-style="{ 'background-color': myform.design.colors.backgroundColor }"> <div class="public-form" ng-style="{ 'background-color': myform.design.colors.backgroundColor }">
<iframe id="iframe" ng-if="!!formURL" ng-src="{{formURL | trustSrc}}" style="border: none; box-shadow: 0px 0px 10px 0px grey; overflow: hidden; height: 400px; width: 90%; position: absolute;"></iframe> <iframe id="iframe" ng-if="!!formURL" ng-src="{{formURL | trustSrc}}" style="border: none; box-shadow: 0px 0px 10px 0px grey; overflow: hidden; height: 400px; width: 90%; position: absolute;"></iframe>
</div> </div>
@ -184,7 +185,7 @@
<div class="row"> <div class="row">
<div class="col-sm-offset-4 col-sm-2"> <div class="col-sm-offset-4 col-sm-2">
<button class="btn btn-signup btn-rounded" type="button" ng-click="update(false, myform, false, false, null)"><i class="icon-arrow-left icon-white"></i>{{ 'SAVE_CHANGES' | translate }}</button> <button class="btn btn-signup btn-rounded" type="button" ng-click="updateDesign(false, myform, false, false)"><i class="icon-arrow-left icon-white"></i>{{ 'SAVE_CHANGES' | translate }}</button>
</div> </div>
<div class="col-sm-1"> <div class="col-sm-1">
<button class="btn btn-secondary btn-rounded" type="button" ng-click="resetForm()"><i class="icon-eye-open icon-white"></i>{{ 'CANCEL' | translate }}</button> <button class="btn btn-secondary btn-rounded" type="button" ng-click="resetForm()"><i class="icon-eye-open icon-white"></i>{{ 'CANCEL' | translate }}</button>

View File

@ -11,37 +11,34 @@
.public-form input, .public-form textarea { .public-form input, .public-form textarea {
background-color: #000000; background-color: #000000;
background-color: rgba(0,0,0,0); background-color: rgba(0,0,0,0);
border: 2px dashed #ddd!important; border-width: 0px;
} }
.public-form input:focus, .public-form textarea:focus { .public-form input.ng-untouched, .public-form textarea.ng-untouched {
border: 2px dashed #ddd!important; border-width: 0 0 2px 0;
border-color: rgba(246, 255, 181, 0.4);
outline: 0; outline: 0;
} }
/*.public-form input.no-border.ng-invalid, .public-form textarea.no-border { .public-form input:focus, .public-form textarea:focus {
border-color: none; border-width: 0 0 2px 0;
}*/ border-color: rgba(246, 255, 181, 0.4);
.public-form input.ng-valid, .public-form textarea.ng-valid { outline: 0;
/*border-color: #20FF20!important;
border-style: solid!important;
border-width: 3px!important;*/
} }
.public-form input.ng-invalid.ng-dirty, .public-form textarea.ng-invalid.ng-dirty { .public-form input.ng-dirty, .public-form textarea.ng-dirty {
/*border-color: #FA787E!important; border-width: 0;
border-style: solid!important; }
border-width: 3px!important;*/
.public-form input.empty, .public-form textarea.empty {
border-width: 0 0 2px 0;
border-color: rgba(246, 255, 181, 0.4);
} }
section.content p.breakwords { section.content p.breakwords {
word-break: break-all; word-break: break-all;
} }
.public-form .btn {
border: 1px solid #c6c6c6;
}
.public-form .btn[type='submit'] { .public-form .btn[type='submit'] {
font-size: 1.5em; font-size: 1.5em;
padding: 0.35em 1.2em 0.35em 1.2em; padding: 0.35em 1.2em 0.35em 1.2em;
@ -142,7 +139,7 @@ form .row.field {
form .row.field > .field-title { form .row.field > .field-title {
margin-top:0.5em; margin-top:0.5em;
font-size:1.2em; font-size:1.2em;
padding-bottom: 1.8em; padding-bottom: 0.5em;
width: inherit; width: inherit;
} }
form .row.field > .field-input { form .row.field > .field-input {
@ -243,15 +240,12 @@ form .row.field {
} }
/* Styles for form list view (/forms) */ /* Styles for form list view (/forms) */
section.public-form { section.public-form field-directive .btn.btn-lg.btn-default {
padding: 0 10% 0 10%; background: none;
}
section.public-form .form-submitted {
position: absolute;
} }
section.public-form .btn { section.public-form field-directive .btn[disabled]{
border: 1px solid; display: none;
} }
.form-item { .form-item {
@ -330,42 +324,16 @@ section.public-form .btn {
top:0; top:0;
} }
/*Modal overlay (for lightbox effect)*/ .field-directive {
.overlay { opacity: 0.2;
position: fixed; padding: 2.5% 10% 2.5% 10%;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: #000;
background-color: rgba(0,0,0,0.5);
z-index: 10;
}
.overlay.submitform {
background-color: #fff;
background-color: rgba(256,256,256,0.8);
} }
.field-directive { .form-field-wrapper .form-actions.activeField, .field-directive.activeField {
z-index: 9; opacity: 1;
padding: 10% 10% 10% 0;
border: 25px transparent solid;
position: relative;
} }
.activeField {
z-index: 11;
position: relative;
background-color: transparent;
}
.activeField.field-directive {
display: inline-block;
border-radius: 7px;
width: 100%;
border: 25px transparent solid;
}
.activeField input {
background-color: transparent;
}
h3.forms-list-title { h3.forms-list-title {
color: #3FA2F7; color: #3FA2F7;
font-weight: 600; font-weight: 600;