1
0

Merge branch 'logic_jump' into stage

This commit is contained in:
David Baldwynn 2016-10-07 08:30:09 -07:00
commit 1d65da9792
25 changed files with 460 additions and 142 deletions

View File

@ -260,7 +260,7 @@ exports.update = function(req, res) {
} }
form = _.extend(form, req.body.form); form = _.extend(form, req.body.form);
} }
form.save(function(err, form) { form.save(function(err, form) {
if (err) { if (err) {

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,76 @@
var mongoose = require('mongoose'), var mongoose = require('mongoose'),
Schema = mongoose.Schema, Schema = mongoose.Schema,
_ = require('lodash'), _ = require('lodash'),
math = require('math'); math = require('mathjs');
var schemaOptions = {
var BooleanExpressionSchema = new Schema({ toObject: {
expressionString: { virtuals: true
type: String,
}, },
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: [
'field == static',
'field != static',
'field > static',
'field >= static',
'field <= static',
'field < static',
'field contains static',
'field !contains static',
'field begins static',
'field !begins static',
'field ends static',
'field !ends static',
]
}, },
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
*/
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

@ -36,9 +36,16 @@
"js-yaml": "^3.6.1", "js-yaml": "^3.6.1",
"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",
<<<<<<< HEAD
"ng-device-detector": "^3.0.1", "ng-device-detector": "^3.0.1",
"ng-translate": "*", "ng-translate": "*",
"deep-diff": "^0.3.4" "deep-diff": "^0.3.4"
=======
"ng-device-detector": "~3.0.1",
"ng-translate": "*",
"mathjs": "^3.4.1",
"jsep": "^0.3.1"
>>>>>>> logic_jump
}, },
"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",
@ -65,6 +66,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,41 @@
'use strict'; 'use strict';
//FIXME: Should find an appropriate place for this
//Setting up jsep
jsep.addBinaryOp("contains", 10);
jsep.addBinaryOp("!contains", 10);
jsep.addBinaryOp("begins", 10);
jsep.addBinaryOp("!begins", 10);
jsep.addBinaryOp("ends", 10);
jsep.addBinaryOp("!ends", 10);
/**
* 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 +128,67 @@ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCoun
/* /*
** Field Controls ** Field Controls
*/ */
var evaluateLogicJump = function(field){
console.log('evaluateLogicJump');
console.log(field.fieldValue);
var logicJump = field.logicJump;
if (logicJump.expressionString && logicJump.valueB && field.fieldValue) {
var parse_tree = jsep(logicJump.expressionString);
var left, right;
console.log(parse_tree);
if(parse_tree.left.name === 'field'){
left = field.fieldValue;
right = logicJump.valueB
} else {
left = logicJump.valueB;
right = field.fieldValue;
}
if(field.fieldType === 'number' || field.fieldType === 'scale' || field.fieldType === 'rating'){
switch(parse_tree.operator) {
case '==':
return (parseInt(left) === parseInt(right));
case '!==':
return (parseInt(left) !== parseInt(right));
case '>':
return (parseInt(left) > parseInt(right));
case '>=':
return (parseInt(left) > parseInt(right));
case '<':
return (parseInt(left) < parseInt(right));
case '<=':
return (parseInt(left) <= parseInt(right));
default:
return false;
}
} else {
switch(parse_tree.operator) {
case '==':
return (left === right);
case '!==':
return (left !== right);
case 'contains':
return (left.indexOf(right) > -1);
case '!contains':
return !(left.indexOf(right) > -1);
case 'begins':
return left.startsWith(right);
case '!begins':
return !left.startsWith(right);
case 'ends':
return left.endsWith(right);
case '!ends':
return left.endsWith(right);
default:
return false;
}
}
}
};
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 +214,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 +265,26 @@ 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($scope.myform.visible_form_fields.length-1); if($scope.selected && $scope.selected.index > -1){
var selected_index, selected_id; //Jump to logicJump's destination if it is true
if($scope.selected.index < $scope.myform.visible_form_fields.length-1){ if(currField.logicJump && evaluateLogicJump(currField)){
selected_index = $scope.selected.index+1; $rootScope.setActiveField(currField.logicJump.jumpTo, null, true);
selected_id = $scope.myform.visible_form_fields[selected_index]._id; } else {
$rootScope.setActiveField(selected_id, selected_index, true); var selected_index, selected_id;
} else if($scope.selected.index === $scope.myform.visible_form_fields.length-1) { 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 = $scope.myform.visible_form_fields[selected_index]._id;
selected_id = 'submit_field'; $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) {
selected_index = $scope.selected.index+1;
selected_id = 'submit_field';
$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

@ -62,24 +62,24 @@ 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 [];
};
/* /*
** FormFields (ui-sortable) drag-and-drop configuration ** FormFields (ui-sortable) drag-and-drop configuration
@ -113,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)){

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,106 @@
</div> </div>
</div> </div>
<div class="row" ng-if="myform.form_fields.length > 1">
<h4> Logic Jump </h4>
</div>
<div class="row" ng-if="myform.form_fields.length > 1">
<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">
<!-- FIX ME: translate this -->
<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="field == static">
<!-- FIX ME: translate this -->
is equal to
</option>
<option value="field != static">
<!-- FIX ME: translate this -->
is not equal to
</option>
<option value="field > static" ng-if-start="field.fieldType === 'number' || field.fieldType === 'rating' || field.fieldType === 'number'">
<!-- FIX ME: translate this -->
is greater than
</option>
<option value="field >= static">
<!-- FIX ME: translate this -->
is greater or equal than
</option>
<option value="field < static">
<!-- FIX ME: translate this -->
is smaller than
</option>
<option value="field <= static" ng-if-end>
<!-- FIX ME: translate this -->
is smaller or equal than
</option>
<option value="field contains static" ng-if-start="field.fieldType !== 'number' && field.fieldType !== 'rating' && field.fieldType !== 'number'">
<!-- FIX ME: translate this -->
contains
</option>
<option value="field !contains static">
<!-- FIX ME: translate this -->
does not contain
</option>
<option value="field ends static">
<!-- FIX ME: translate this -->
ends with
</option>
<option value="field !ends static">
<!-- FIX ME: translate this -->
does not end with
</option>
<option value="field starts static">
<!-- FIX ME: translate this -->
starts with
</option>
<option value="field !starts static" ng-if-end>
<!-- FIX ME: translate this -->
does not start with
</option>
</select>
</div>
<div class="col-md-4 col-sm-12">
<input type="text" ng-model="field.logicJump.valueB"/>
</div>
<div class="col-md-2">
<!-- FIX ME: translate this -->
<b>Jumps to </b>
</div>
<div class="col-md-10">
<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