added logicjump to forms

This commit is contained in:
David Baldwynn 2016-08-23 14:45:59 -07:00
parent de5ac881c9
commit 02e25ef739
26 changed files with 369 additions and 220 deletions

View file

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

View file

@ -69,74 +69,6 @@ exports.uploadPDF = function(req, res, next) {
} }
}; };
/**
* Upload PDF
*/
/*
exports.uploadSubmissionFile = function(req, res, next) {
console.log('inside uploadPDF');
// console.log('\n\nProperty Descriptor\n-----------');
// console.log(Object.getOwnPropertyDescriptor(req.files.file, 'path'));
console.log(req.files);
if(req.files){
var file, _user, _path;
for(var i=0; i<req.files.length; i++){
file = req.files[i];
_user = req.user;
_path = file.path;
if (file.size === 0) {
return next(new Error('File uploaded is EMPTY'));
}else if(file.size > 100000000){
return next(new Error('File uploaded exceeds MAX SIZE of 100MB'));
}else {
fs.exists(_path, function(exists) {
//If file exists move to user's form directory
if(exists) {
var newDestination = config.tmpUploadPath+_user.username;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
console.log('Directory cannot be created');
return next(new Error('Directory cannot be created because an inode of a different type exists at "' + newDestination + '"'));
}
console.log(path.join(newDestination, pdfFile.filename));
fs.move(pdfFile.path, path.join(newDestination, pdfFile.filename), function (err) {
if (err) {
return next(new Error(err.message));
}
pdfFile.path = path.join(newDestination, pdfFile.filename);
console.log(pdfFile.filename + ' uploaded to ' + pdfFile.path);
res.json(pdfFile);
});
} else {
return next(new Error('Did NOT get your file!'));
}
});
}
}
}else {
return next(new Error('Uploaded files were NOT detected'));
}
};
*/
/** /**
* Delete a forms submissions * Delete a forms submissions
*/ */
@ -311,6 +243,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++){
delete req.body.form.form_fields[i].input_type;
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

@ -7,7 +7,8 @@ var mongoose = require('mongoose'),
util = require('util'), util = require('util'),
mUtilities = require('mongoose-utilities'), mUtilities = require('mongoose-utilities'),
_ = require('lodash'), _ = require('lodash'),
Schema = mongoose.Schema; Schema = mongoose.Schema,
LogicJumpSchema = require('./logic_jump.server.model');
var FieldOptionSchema = new Schema({ var FieldOptionSchema = new Schema({
option_id: { option_id: {
@ -77,10 +78,7 @@ function BaseFieldSchema(){
default: '' default: ''
}, },
logicJump: { logicJump: LogicJumpSchema,
type: Schema.Types.ObjectId,
ref: 'LogicJump'
},
ratingOptions: { ratingOptions: {
type: RatingFieldSchema, type: RatingFieldSchema,
@ -162,6 +160,7 @@ FormFieldSchema.pre('validate', function(next) {
if(this.ratingOptions && this.ratingOptions.steps && this.ratingOptions.shape){ if(this.ratingOptions && this.ratingOptions.steps && this.ratingOptions.shape){
error.errors.ratingOptions = new mongoose.Error.ValidatorError({path: 'ratingOptions', message: 'ratingOptions is only allowed for type \'rating\' fields.', type: 'notvalid', value: this.ratingOptions}); error.errors.ratingOptions = new mongoose.Error.ValidatorError({path: 'ratingOptions', message: 'ratingOptions is only allowed for type \'rating\' fields.', type: 'notvalid', value: this.ratingOptions});
console.error(error);
return(next(error)); return(next(error));
} }
@ -183,8 +182,9 @@ FormFieldSchema.pre('validate', function(next) {
//If field is multiple choice check that it has field //If field is multiple choice check that it has field
if(this.fieldType !== 'dropdown' && this.fieldType !== 'radio' && this.fieldType !== 'checkbox'){ if(this.fieldType !== 'dropdown' && this.fieldType !== 'radio' && this.fieldType !== 'checkbox'){
if(!this.fieldOptions || this.fieldOptions.length !== 0){ if(this.fieldOptions && this.fieldOptions.length > 0){
error.errors.ratingOptions = new mongoose.Error.ValidatorError({path:'fieldOptions', message: 'fieldOptions are only allowed for type dropdown, checkbox or radio fields.', type: 'notvalid', value: this.ratingOptions}); error.errors.ratingOptions = new mongoose.Error.ValidatorError({path:'fieldOptions', message: 'fieldOptions are only allowed for type dropdown, checkbox or radio fields.', type: 'notvalid', value: this.ratingOptions});
console.error(error);
return(next(error)); return(next(error));
} }
} }
@ -192,13 +192,18 @@ FormFieldSchema.pre('validate', function(next) {
return next(); return next();
}); });
//LogicJump Save
FormFieldSchema.pre('save', function(next) {
if(this.logicJump && this.logicJump.fieldA){
if(this.logicJump.jumpTo = '') delete this.logicJump.jumpTo;
}
next();
});
//Submission fieldValue correction //Submission fieldValue correction
FormFieldSchema.pre('save', function(next) { FormFieldSchema.pre('save', function(next) {
if(this.fieldType === 'dropdown' && this.isSubmission){ if(this.fieldType === 'dropdown' && this.isSubmission){
//console.log(this);
this.fieldValue = this.fieldValue.option_value; this.fieldValue = this.fieldValue.option_value;
//console.log(this.fieldValue);
} }
return next(); return next();

View file

@ -6,76 +6,108 @@
var mongoose = require('mongoose'), var mongoose = require('mongoose'),
Schema = mongoose.Schema, Schema = mongoose.Schema,
_ = require('lodash'), _ = require('lodash'),
math = require('math'); math = require('mathjs');
/**
* Calculate a 32 bit FNV-1a hash
* Found here: https://gist.github.com/vaiorabbit/5657561
* Ref.: http://isthe.com/chongo/tech/comp/fnv/
*
* @param {string} str the input value
* @param {boolean} [asString=false] set to true to return the hash value as
* 8-digit hex string instead of an integer
* @param {integer} [seed] optionally pass the hash of the previous chunk
* @returns {integer | string}
*/
function hashFnv32a(str, asString, seed) {
/*jshint bitwise:false */
var i, l,
hval = (seed === undefined) ? 0x811c9dc5 : seed;
var BooleanExpressionSchema = new Schema({ for (i = 0, l = str.length; i < l; i++) {
expressionString: { hval ^= str.charCodeAt(i);
type: String, hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
}
if( asString ){
// Convert to 8 digit hex string
return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
}
return hval >>> 0;
}
var schemaOptions = {
toObject: {
virtuals: true
}, },
result: { toJSON: {
type: Boolean, virtuals: true
}
});
BooleanExpressionSchema.methods.evaluate = function(){
if(this.expressionString){
//Get headNode
var headNode = math.parse(this.expressionString);
var expressionScope = {};
var that = this;
//Create scope
headNode.traverse(function (node, path, parent) {
if(node.type === 'SymbolNode'){
mongoose.model('Field')
.findOne({_id: node.name}).exec(function(err, field){
if(err) {
console.log(err);
throw new Error(err);
}
if(!!_.parseInt(field.fieldValue)){
that.expressionScope[node.name] = _.parseInt(field.fieldValue);
}else {
that.expressionScope[node.name] = field.fieldValue;
}
console.log('_id: '+node.name);
console.log('value: '+that.expressionScope[node.name]);
});
}
});
var code = headNode.compile();
var result = code.eval(expressionScope);
this.result = result;
return result;
}else{
return null;
} }
}; };
mongoose.model('BooleanExpression', BooleanExpressionSchema);
/**
* Form Schema
*/
var LogicJumpSchema = new Schema({ var LogicJumpSchema = new Schema({
created: { expressionString: {
type: Date, type: String,
default: Date.now enum: [
'a == b',
'a !== b'
]
}, },
lastModified: { fieldA: {
type: Date,
},
BooleanExpression: {
type: Schema.Types.ObjectId, type: Schema.Types.ObjectId,
ref: 'BooleanExpression' ref: 'FormField'
}, },
valueB: {
type: Schema.Types.String
},
jumpTo: {
type: Schema.Types.ObjectId,
ref: 'FormField'
}
}, schemaOptions);
/*
IS EQUAL TO statement
var scope = {
a: val1,
b: val2
};
math.eval('a == b', scope);
IS NOT EQUAL TO statement
var scope = {
a: val1,
b: val2
};
math.eval('a !== b', scope);
BEGINS WITH statement
ENDS WITH statement
CONTAINS statement
DOES NOT CONTAIN statement
*/
LogicJumpSchema.virtual('result').get(function () {
if (this.expressionString && this.fieldA.fieldValue && this.valueB) {
var valA = hashFnv32a(String(this.fieldA.fieldValue));
var valB = hashFnv32a(String(this.valueB));
var scope = {
'a': valA,
'b': valB
};
return math.eval(this.expressionString, scope);
} else {
return null;
}
}); });
mongoose.model('LogicJump', LogicJumpSchema); mongoose.model('LogicJump', LogicJumpSchema);
module.exports = LogicJumpSchema;

View file

@ -2,7 +2,7 @@
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<title>{{title}}</title> <title>{{title}} Form</title>
<!-- General META --> <!-- General META -->
<meta charset="utf-8"> <meta charset="utf-8">

View file

@ -37,7 +37,8 @@
"angular-ui-select": "https://github.com/whitef0x0/ui-select.git#compiled", "angular-ui-select": "https://github.com/whitef0x0/ui-select.git#compiled",
"angular-translate": "~2.11.0", "angular-translate": "~2.11.0",
"ng-device-detector": "~3.0.1", "ng-device-detector": "~3.0.1",
"ng-translate": "*" "ng-translate": "*",
"mathjs": "^3.4.1"
}, },
"resolutions": { "resolutions": {
"angular-bootstrap": "^0.14.0", "angular-bootstrap": "^0.14.0",

View file

@ -72,6 +72,7 @@ module.exports = function(db) {
var subdomains = req.subdomains; var subdomains = req.subdomains;
var host = req.hostname; var host = req.hostname;
console.log(subdomains);
if(subdomains.slice(0, 4).join('.')+'' === '1.0.0.127'){ if(subdomains.slice(0, 4).join('.')+'' === '1.0.0.127'){
subdomains = subdomains.slice(4); subdomains = subdomains.slice(4);
@ -81,18 +82,18 @@ module.exports = function(db) {
if (!subdomains.length) return next(); if (!subdomains.length) return next();
var urlPath = url.parse(req.url).path.split('/'); var urlPath = url.parse(req.url).path.split('/');
if(urlPath.indexOf('static')){ if(urlPath.indexOf('static') > -1){
urlPath.splice(1,1); urlPath.splice(1,1);
req.root = 'https://' + config.baseUrl + urlPath.join('/'); req.root = 'https://' + config.baseUrl + urlPath.join('/');
return next(); return next();
} }
if(subdomains.indexOf('stage') || subdomains.indexOf('admin')){ if(subdomains.indexOf('stage') > -1 || subdomains.indexOf('admin') > -1){
return next(); return next();
} }
User.findOne({username: req.subdomains.reverse()[0]}).exec(function (err, user) { User.findOne({username: req.subdomains.reverse()[0]}).exec(function (err, user) {
console.log(user);
if (err) { if (err) {
console.log(err); console.log(err);
req.subdomains = null; req.subdomains = null;
@ -117,6 +118,8 @@ module.exports = function(db) {
req.userId = user._id; req.userId = user._id;
console.log('\n\n\ngot subdomain: '+ req.subdomains.reverse()[0]);
// Q.E.D. // Q.E.D.
next(); next();
}); });

View file

@ -24,6 +24,7 @@
}, },
"dependencies": { "dependencies": {
"async": "^1.4.2", "async": "^1.4.2",
"async-boolean-expression-evaluator": "^1.1.1",
"aws-sdk": "^2.3.9", "aws-sdk": "^2.3.9",
"bcrypt": "^0.8.7", "bcrypt": "^0.8.7",
"body-parser": "~1.14.1", "body-parser": "~1.14.1",
@ -64,6 +65,7 @@
"lodash": "^2.4.1", "lodash": "^2.4.1",
"main-bower-files": "~2.9.0", "main-bower-files": "~2.9.0",
"math": "0.0.3", "math": "0.0.3",
"mathjs": "^3.4.1",
"method-override": "~2.3.0", "method-override": "~2.3.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"mongoose": "~4.4.19", "mongoose": "~4.4.19",

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

@ -1,5 +1,32 @@
'use strict'; 'use strict';
/**
* Calculate a 32 bit FNV-1a hash
* Found here: https://gist.github.com/vaiorabbit/5657561
* Ref.: http://isthe.com/chongo/tech/comp/fnv/
*
* @param {string} str the input value
* @param {boolean} [asString=false] set to true to return the hash value as
* 8-digit hex string instead of an integer
* @param {integer} [seed] optionally pass the hash of the previous chunk
* @returns {integer | string}
*/
function hashFnv32a(str, asString, seed) {
/*jshint bitwise:false */
var i, l,
hval = (seed === undefined) ? 0x811c9dc5 : seed;
for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
}
if( asString ){
// Convert to 8 digit hex string
return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
}
return hval >>> 0;
}
;
angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData',
function ($http, TimeCounter, $filter, $rootScope, SendVisitorData) { function ($http, TimeCounter, $filter, $rootScope, SendVisitorData) {
@ -92,6 +119,20 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
/* /*
** Field Controls ** Field Controls
*/ */
var evaluateLogicJump = function(field){
console.log('evaluateLogicJump');
var logicJump = field.logicJump;
if (logicJump.expressionString && logicJump.valueB) {
var valA = hashFnv32a(String(field.fieldValue));
var valB = hashFnv32a(String(logicJump.valueB));
var scope = {
'a': valA,
'b': valB
};
return math.eval(logicJump.expressionString, scope);
}
};
var getActiveField = function(){ var getActiveField = function(){
if($scope.selected === null){ if($scope.selected === null){
console.error('current active field is null'); console.error('current active field is null');
@ -117,6 +158,15 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
$scope.selected._id = field_id; $scope.selected._id = field_id;
$scope.selected.index = field_index; $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];
if(field_id == currField._id){
$scope.selected.index = i;
break;
}
}
}
var nb_valid = $filter('formValidity')($scope.myform); var nb_valid = $filter('formValidity')($scope.myform);
$scope.translateAdvancementData = { $scope.translateAdvancementData = {
@ -159,20 +209,27 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
}; };
$rootScope.nextField = $scope.nextField = function(){ $rootScope.nextField = $scope.nextField = function(){
//console.log('nextfield'); var currField = $scope.myform.visible_form_fields[$scope.selected.index];
//console.log($scope.selected.index); console.log(currField.logicJump);
//console.log($scope.myform.visible_form_fields.length-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; var selected_index, selected_id;
if($scope.selected.index < $scope.myform.visible_form_fields.length-1){ if($scope.selected.index < $scope.myform.visible_form_fields.length-1){
selected_index = $scope.selected.index+1; selected_index = $scope.selected.index+1;
selected_id = $scope.myform.visible_form_fields[selected_index]._id; selected_id = $scope.myform.visible_form_fields[selected_index]._id;
$rootScope.setActiveField(selected_id, selected_index, true); $rootScope.setActiveField(selected_id, selected_index, true);
} else if($scope.selected.index === $scope.myform.visible_form_fields.length-1) { } else if($scope.selected.index === $scope.myform.visible_form_fields.length-1) {
//console.log('Second last element');
selected_index = $scope.selected.index+1; selected_index = $scope.selected.index+1;
selected_id = 'submit_field'; selected_id = 'submit_field';
$rootScope.setActiveField(selected_id, selected_index, true); $rootScope.setActiveField(selected_id, selected_index, true);
} }
}
}
}; };
$rootScope.prevField = $scope.prevField = function(){ $rootScope.prevField = $scope.prevField = function(){

View file

@ -51,7 +51,7 @@
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 || forms.myForm.{{field.fieldType}}{{$index}}.$invalid" <button ng-disabled="!field.fieldValue || forms.myForm.{{field.fieldType}}{{$index}}.$invalid"
ng-style="{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}" ng-style="{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}"
ng-click="$root.nextField()" ng-click="nextField()"
class="btn col-sm-5 col-xs-5"> class="btn col-sm-5 col-xs-5">
{{ 'OK' | translate }} <i class="fa fa-check"></i> {{ 'OK' | translate }} <i class="fa fa-check"></i>

View file

@ -4,4 +4,4 @@
ApplicationConfiguration.registerModule('view-form', [ ApplicationConfiguration.registerModule('view-form', [
'ngFileUpload', 'ui.router.tabs', 'ui.date', 'ui.sortable', 'ngFileUpload', 'ui.router.tabs', 'ui.date', 'ui.sortable',
'angular-input-stars', 'pascalprecht.translate' 'angular-input-stars', 'pascalprecht.translate'
]);//, 'colorpicker.module' @TODO reactivate this module ]);

View file

@ -39,6 +39,10 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
PREVIEW: 'Preview', PREVIEW: 'Preview',
//Edit Form View //Edit Form View
DISABLED: 'Disabled:',
YES: 'YES',
NO: 'NO',
ADD_LOGIC_JUMP: 'Add Logic Jump',
ADD_FIELD_LG: 'Click to Add New Field', ADD_FIELD_LG: 'Click to Add New Field',
ADD_FIELD_MD: 'Add New Field', ADD_FIELD_MD: 'Add New Field',
ADD_FIELD_SM: 'Add Field', ADD_FIELD_SM: 'Add Field',

View file

@ -10,7 +10,6 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
}, },
controller: function($scope){ controller: function($scope){
console.log($scope.myform);
var field_ids = _($scope.myform.form_fields).pluck('_id'); var field_ids = _($scope.myform.form_fields).pluck('_id');
for(var i=0; i<field_ids.length; i++){ for(var i=0; i<field_ids.length; i++){
$scope.myform.plugins.oscarhost.settings.fieldMap[field_ids[i]] = null; $scope.myform.plugins.oscarhost.settings.fieldMap[field_ids[i]] = null;
@ -63,23 +62,23 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
//Populate local scope with rootScope methods/variables //Populate local scope with rootScope methods/variables
$scope.update = $rootScope.update; $scope.update = $rootScope.update;
//Many-to-many Select for Mapping OscarhostFields -> FormFields // LOGIC JUMP METHODS
$scope.oscarFieldsLeft = function(field_id){ $scope.removeLogicJump = function (field_index) {
var currField = $scope.myform.form_fields[field_index];
currField.logicJump = {};
};
if($scope.myform && $scope.myform.plugins.oscarhost.settings.validFields.length > 0){ $scope.addNewLogicJump = function (field_index) {
if(!$scope.myform.plugins.oscarhost.settings.fieldMap) $scope.myform.plugins.oscarhost.settings.fieldMap = {}; var form_fields = $scope.myform.form_fields;
var currField = form_fields[field_index];
console.log(currField);
if (form_fields.length > 1 && currField._id) {
var oscarhostFields = $scope.myform.plugins.oscarhost.settings.validFields; var newLogicJump = {
var currentFields = _($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value(); fieldA: currField._id
};
if( $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id) ){ currField.logicJump = newLogicJump;
currentFields = _(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id]);
} }
//Get all oscarhostFields that haven't been mapped to a formfield
return _(oscarhostFields).difference(currentFields).value();
}
return [];
}; };
/* /*
@ -114,7 +113,8 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
fieldValue: '', fieldValue: '',
required: true, required: true,
disabled: false, disabled: false,
deletePreserved: false deletePreserved: false,
logicJump: {}
}; };
if($scope.showAddOptions(newField)){ if($scope.showAddOptions(newField)){
@ -126,7 +126,6 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
}); });
} }
if(modifyForm){ if(modifyForm){
//Add newField to form_fields array //Add newField to form_fields array
$scope.myform.form_fields.push(newField); $scope.myform.form_fields.push(newField);

View file

@ -249,7 +249,6 @@
</div> </div>
</div> </div>
<div class="row" ng-show="showRatingOptions(field)"><br></div> <div class="row" ng-show="showRatingOptions(field)"><br></div>
<div class="row" ng-if="showRatingOptions(field)"> <div class="row" ng-if="showRatingOptions(field)">
<div class="col-md-9 col-sm-9">{{ 'NUM_OF_STEPS' | translate }}</div> <div class="col-md-9 col-sm-9">{{ 'NUM_OF_STEPS' | translate }}</div>
@ -293,7 +292,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-4 col-xs-12 field-input">Disabled:</div> <div class="col-md-4 col-xs-12 field-input">{{ 'DISABLED' | translate }}</div>
<div class="col-md-8 col-xs-12 field-input"> <div class="col-md-8 col-xs-12 field-input">
<label class="btn col-xs-5"> <label class="btn col-xs-5">
<input type="radio" ng-value="true" <input type="radio" ng-value="true"
@ -309,6 +308,60 @@
</div> </div>
</div> </div>
<div class="row" ng-if="myform.form_fields.length > 1 && myform.form_fields[$index].logicJump.fieldA">
<h4> Logic Jump </h4>
</div>
<div class="row" ng-if="myform.form_fields.length > 1 && myform.form_fields[$index].logicJump.fieldA">
<div class="col-md-4 col-xs-12 field-input">{{ 'ADD_LOGIC_JUMP' | translate }}</div>
<div class="col-md-8 col-xs-12 field-input">
<label class="btn col-xs-5">
<input type="radio" ng-checked="!!myform.form_fields[$index].logicJump.fieldA"
name="logicJumpYes{{field._id}}" ng-click="addNewLogicJump($index)"/>
<span> &nbsp; {{ 'YES' | translate }}</span>
</label>
<label class="btn col-xs-5 col-xs-offset-1">
<input type="radio" ng-checked="!myform.form_fields[$index].logicJump.fieldA"
name="logicJumpNo{{field._id}}" ng-click="removeLogicJump($index)"/>
<span> &nbsp; {{ 'NO' | translate }}</span>
</label>
</div>
</div>
<div class="row question" ng-if="myform.form_fields.length > 1 && myform.form_fields[$index].logicJump.fieldA">
<div class="col-md-4 col-sm-12">
<b> If this field </b>
</div>
<div class="col-md-4 col-sm-12">
<select style="width:100%" ng-model="field.logicJump.expressionString"
value="{{field.logicJump.expressionString}}"
name="logicjump_expressionString{{field._id}}">
<option value="a == b">
is equal to
</option>
<option value="a !== b">
is not equal to
</option>
</select>
</div>
<div class="col-md-4 col-sm-12">
<input type="text" ng-model="field.logicJump.valueB"/>
</div>
<div class="col-md-4 col-md-offset-2">
<b>Jumps to </b>
</div>
<div class="col-md-6 col-sm-12">
<select style="width:100%" ng-model="field.logicJump.jumpTo"
value="{{field.logicJump.jumpTo}}"
name="logicjump_jumpTo{{field._id}}">
<option ng-repeat="jump_field in myform.form_fields"
value="{{jump_field._id}}">
{{jump_field.title}}
</option>
</select>
</div>
</div>
</div> </div>
</accordion-group> </accordion-group>

0
public/modules/forms/base/bower.json Executable file → Normal file
View file

View file

View file

View file

View file

View file

View file