added multiple choice default options
This commit is contained in:
parent
29667e5537
commit
6131f7de94
|
@ -210,7 +210,6 @@ exports.createSubmission = function(req, res) {
|
|||
}
|
||||
|
||||
submission.save(function(err, submission){
|
||||
// console.log('in submissions.save()\n submission: '+JSON.stringify(submission) )
|
||||
if(err){
|
||||
console.log(err.message);
|
||||
res.status(400).send({
|
||||
|
|
|
@ -65,10 +65,8 @@ var FormSchema = new Schema({
|
|||
type: String,
|
||||
default: ''
|
||||
},
|
||||
form_fields: {
|
||||
type: [FieldSchema]
|
||||
},
|
||||
|
||||
form_fields: [FieldSchema],
|
||||
submissions: [{
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'FormSubmission'
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Module dependencies.
|
||||
*/
|
||||
var mongoose = require('mongoose'),
|
||||
util = require('util'),
|
||||
mUtilities = require('mongoose-utilities'),
|
||||
_ = require('lodash'),
|
||||
Schema = mongoose.Schema;
|
||||
|
@ -23,85 +24,184 @@ var FieldOptionSchema = new Schema({
|
|||
}
|
||||
});
|
||||
|
||||
var RatingFieldSchema = new Schema({
|
||||
steps: {
|
||||
type: Number
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
enum: [
|
||||
'Heart',
|
||||
'Star',
|
||||
'thumbs-up',
|
||||
'thumbs-down',
|
||||
'Circle',
|
||||
'Square',
|
||||
'Check Circle',
|
||||
'Smile Outlined',
|
||||
'Hourglass',
|
||||
'bell',
|
||||
'Paper Plane',
|
||||
'Comment',
|
||||
'Trash'
|
||||
]
|
||||
},
|
||||
validShapes: {
|
||||
type: [String]
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* FormField Schema
|
||||
*/
|
||||
var FormFieldSchema = new Schema({
|
||||
title: {
|
||||
type: String,
|
||||
trim: true,
|
||||
required: 'Field Title cannot be blank'
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
function BaseFieldSchema(){
|
||||
Schema.apply(this, arguments);
|
||||
|
||||
logicJump: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'LogicJump'
|
||||
},
|
||||
this.add({
|
||||
title: {
|
||||
type: String,
|
||||
trim: true,
|
||||
required: 'Field Title cannot be blank'
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
fieldOptions: [FieldOptionSchema],
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
logicJump: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'LogicJump'
|
||||
},
|
||||
|
||||
deletePreserved: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
validFieldTypes: {
|
||||
type: [String]
|
||||
},
|
||||
fieldType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'textfield',
|
||||
'date',
|
||||
'email',
|
||||
'link',
|
||||
'legal',
|
||||
'url',
|
||||
'textarea',
|
||||
'statement',
|
||||
'welcome',
|
||||
'thankyou',
|
||||
'file',
|
||||
'dropdown',
|
||||
'scale',
|
||||
'rating',
|
||||
'radio',
|
||||
'checkbox',
|
||||
'hidden',
|
||||
'yes_no',
|
||||
'natural',
|
||||
'number'
|
||||
]
|
||||
},
|
||||
fieldValue: Schema.Types.Mixed
|
||||
});
|
||||
ratingOptions: {
|
||||
type: RatingFieldSchema,
|
||||
required: false,
|
||||
default: {}
|
||||
},
|
||||
fieldOptions: [FieldOptionSchema],
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
FormFieldSchema.plugin(mUtilities.timestamp, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
});
|
||||
deletePreserved: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
validFieldTypes: {
|
||||
type: [String]
|
||||
},
|
||||
fieldType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'textfield',
|
||||
'date',
|
||||
'email',
|
||||
'link',
|
||||
'legal',
|
||||
'url',
|
||||
'textarea',
|
||||
'statement',
|
||||
'welcome',
|
||||
'thankyou',
|
||||
'file',
|
||||
'dropdown',
|
||||
'scale',
|
||||
'rating',
|
||||
'radio',
|
||||
'checkbox',
|
||||
'hidden',
|
||||
'yes_no',
|
||||
'natural',
|
||||
'number'
|
||||
]
|
||||
},
|
||||
fieldValue: Schema.Types.Mixed
|
||||
});
|
||||
|
||||
FormFieldSchema.pre('save', function (next){
|
||||
this.validFieldTypes = mongoose.model('Field').schema.path('fieldType').enumValues;
|
||||
next();
|
||||
this.plugin(mUtilities.timestamp, {
|
||||
createdPath: 'created',
|
||||
modifiedPath: 'lastModified',
|
||||
useVirtual: false
|
||||
});
|
||||
|
||||
this.pre('save', function (next) {
|
||||
this.validFieldTypes = mongoose.model('Field').schema.path('fieldType').enumValues;
|
||||
|
||||
if(this.fieldType === 'rating' && this.ratingOptions.validShapes.length === 0){
|
||||
this.ratingOptions.validShapes = mongoose.model('RatingOptions').schema.path('shape').enumValues;
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
util.inherits(BaseFieldSchema, Schema);
|
||||
|
||||
var FormFieldSchema = new BaseFieldSchema();
|
||||
|
||||
FormFieldSchema.pre('validate', function(next) {
|
||||
var error = new mongoose.Error.ValidationError(this);
|
||||
|
||||
//If field is rating check that it has ratingOptions
|
||||
if(this.fieldType !== 'rating'){
|
||||
|
||||
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});
|
||||
return(next(error));
|
||||
}
|
||||
|
||||
}else{
|
||||
//Setting default values for ratingOptions
|
||||
if(!this.ratingOptions.steps){
|
||||
this.ratingOptions.steps = 10;
|
||||
}
|
||||
if(!this.ratingOptions.shape){
|
||||
this.ratingOptions.shape = 'Star';
|
||||
}
|
||||
|
||||
//Checking that the fieldValue is between 0 and ratingOptions.steps
|
||||
if(this.fieldValue+0 > this.ratingOptions.steps || this.fieldValue+0 < 0){
|
||||
this.fieldValue = 1;
|
||||
//error.errors.fieldValue = mongoose.Error.ValidatorError({path:'fieldValue', message: 'fieldValue is not within proper range for rating field.', type: 'notvalid', value: this.fieldValue});
|
||||
//return(next(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//If field is multiple choice check that it has ratingOptions
|
||||
if(this.fieldType !== 'dropdown' && this.fieldType !== 'radio' && this.fieldType === 'checkbox'){
|
||||
|
||||
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});
|
||||
return(next(error));
|
||||
}
|
||||
}
|
||||
|
||||
if(error)
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
|
||||
mongoose.model('Field', FormFieldSchema);
|
||||
//Validate and convert dropdown value to fieldValue
|
||||
FormFieldSchema.pre('validate', function (next) {
|
||||
return next();
|
||||
|
||||
/*
|
||||
if(this.fieldType === 'dropdown' && this.fieldOptions.length > 0){
|
||||
for(var i = 0; i<this.fieldOptions.length; i++){
|
||||
|
||||
}
|
||||
}*/
|
||||
});
|
||||
|
||||
|
||||
var Field = mongoose.model('Field', FormFieldSchema);
|
||||
var RatingOptions = mongoose.model('RatingOptions', RatingFieldSchema);
|
||||
|
||||
module.exports = FormFieldSchema;
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
"angular-busy": "^4.1.3",
|
||||
"angular-input-stars": "https://github.com/whitef0x0/angular-input-stars.git#master",
|
||||
"raven-js": "^3.0.4",
|
||||
"tableExport.jquery.plugin": "^1.5.1"
|
||||
"tableExport.jquery.plugin": "^1.5.1",
|
||||
"js-yaml": "^3.6.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"angular-bootstrap": "^0.14.0",
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"math": "0.0.3",
|
||||
"method-override": "~2.3.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mongoose": "3.8.40",
|
||||
"mongoose": "~4.4.19",
|
||||
"mongoose-utilities": "~0.1.1",
|
||||
"morgan": "~1.6.1",
|
||||
"multer": "~1.1.0",
|
||||
|
|
131
public/dist/application.js
vendored
131
public/dist/application.js
vendored
|
@ -57,7 +57,7 @@ angular.module('NodeForm.templates', []).run(['$templateCache', function($templa
|
|||
$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",
|
||||
"<div class=\"field row radio\" on-enter-key=nextField() key-to-option field=field ng-if=\"field.fieldOptions.length > 0\"><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</span></h3></div><div class=\"col-xs-12 field-input\"><div ng-repeat=\"option in field.fieldOptions\" class=row-fluid><label class=\"btn col-md-4 col-xs-12 col-sm-12\" style=\"margin: 0.5em; padding-left:30px\" ng-class=\"{activeBtn: field.fieldValue == field.fieldOptions[$index].option_value}\"><div class=letter style=float:left>{{$index+1}}</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 }\" ng-required=field.required ng-disabled=field.disabled ng-change=\"$root.nextField()\"> <span ng-bind=option.option_value></span></label></div></div></div><br>");
|
||||
$templateCache.put("../public/modules/forms/views/directiveViews/field/rating.html",
|
||||
"<div class=\"textfield field row\" on-enter-key=nextField()><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</span></h3></div><div class=\"col-xs-12 field-input\"><input-stars max=5 ng-init=\"field.fieldValue = 1\" on-star-click=$root.nextField() icon-full=fa-star icon-base=\"fa fa-3x\" icon-empty=fa-star-o ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-disabled=field.disabled class=\"angular-input-stars focusOn\"></input-stars></div></div>");
|
||||
"<div class=\"textfield field row\" on-enter-key=nextField()><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</span></h3></div><div class=\"col-xs-12 field-input\"><input-stars max=5 ng-init=\"field.fieldValue = 1\" on-star-click=$root.nextField() ratingshapeicon=Trash icon-base=\"fa fa-3x\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-disabled=field.disabled class=\"angular-input-stars focusOn\"></input-stars></div></div>");
|
||||
$templateCache.put("../public/modules/forms/views/directiveViews/field/statement.html",
|
||||
"<div class=\"statement field row\" on-enter-key=$root.nextField() ng-focus=\"setActiveField(field._id, index, true)\"><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></div><div class=\"row field-title field-input\"><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\" 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()>Continue</button></div></div></div>");
|
||||
$templateCache.put("../public/modules/forms/views/directiveViews/field/textarea.html",
|
||||
|
@ -1616,7 +1616,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||
'use strict';
|
||||
|
||||
angular.module('forms').directive('fieldIconDirective', function() {
|
||||
|
||||
|
||||
return {
|
||||
template: '<i class="{{typeIcon}}"></i>',
|
||||
restrict: 'E',
|
||||
|
@ -1643,9 +1643,10 @@ angular.module('forms').directive('fieldIconDirective', function() {
|
|||
'number': 'fa fa-slack'
|
||||
};
|
||||
$scope.typeIcon = iconTypeMap[$scope.typeName];
|
||||
}],
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
'use strict';
|
||||
|
||||
// coffeescript's for in loop
|
||||
|
@ -1656,8 +1657,8 @@ var __indexOf = [].indexOf || function(item) {
|
|||
return -1;
|
||||
};
|
||||
|
||||
angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$rootScope', '$templateCache',
|
||||
function($http, $compile, $rootScope, $templateCache) {
|
||||
angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$rootScope', '$templateCache', 'FontAwesomeIcons',
|
||||
function($http, $compile, $rootScope, $templateCache, FontAwesomeIcons) {
|
||||
|
||||
var getTemplateUrl = function(fieldType) {
|
||||
var type = fieldType;
|
||||
|
@ -1677,7 +1678,7 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
'number',
|
||||
'natural'
|
||||
];
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
templateUrl = templateUrl+type+'.html';
|
||||
}
|
||||
return $templateCache.get('../public/'+templateUrl);
|
||||
|
@ -1695,6 +1696,14 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
},
|
||||
link: function(scope, element) {
|
||||
|
||||
FontAwesomeIcons.get(function(data){
|
||||
console.log('font awesome icons');
|
||||
console.log(data);
|
||||
console.log(data.iconCategoryList);
|
||||
console.log(data.iconList);
|
||||
console.log(data.iconMap);
|
||||
});
|
||||
|
||||
$rootScope.chooseDefaultOption = scope.chooseDefaultOption = function(type) {
|
||||
if(type === 'yes_no'){
|
||||
scope.field.fieldValue = 'true';
|
||||
|
@ -1756,26 +1765,21 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
|
||||
angular.module('forms').directive('keyToOption', function(){
|
||||
return {
|
||||
restrict: 'AE',
|
||||
transclude: true,
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
field: '&'
|
||||
field: '='
|
||||
},
|
||||
link: function($scope, $element, $attrs, $select) {
|
||||
$element.bind('keydown keypress', function(event) {
|
||||
|
||||
var keyCode = event.which || event.keyCode;
|
||||
var index = parseInt(String.fromCharCode(keyCode))-1;
|
||||
console.log($scope.field);
|
||||
//console.log($scope.field);
|
||||
|
||||
if (index < $scope.field.fieldOptions.length) {
|
||||
event.preventDefault();
|
||||
$scope.$apply(function () {
|
||||
$scope.field.fieldValue = $scope.field.fieldOptions[index].option_value;
|
||||
if($attrs.type === 'dropdown'){
|
||||
$select.selected.option_value = $scope.field.fieldOptions[index].option_value;
|
||||
}
|
||||
console.log($scope);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1864,6 +1868,64 @@ angular.module('forms').directive('onFinishRender', ["$rootScope", "$timeout", f
|
|||
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('ratingShapeIcon', ['FontAwesomeIcons', function(FontAwesomeIcons) {
|
||||
var getRatingShape = function (fieldType, iconData) {
|
||||
var iconObj = {
|
||||
full: "",
|
||||
base: "fa fa-3x",
|
||||
empty: ""
|
||||
};
|
||||
var supported_fields = [
|
||||
'Heart',
|
||||
'Star',
|
||||
'thumbs-up',
|
||||
'thumbs-down',
|
||||
'Circle',
|
||||
'Square',
|
||||
'Check Circle',
|
||||
'Smile Outlined',
|
||||
'Hourglass',
|
||||
'bell',
|
||||
'Paper Plane',
|
||||
'Comment',
|
||||
'Trash'
|
||||
];
|
||||
if (__indexOf.call(iconData.iconList, fieldType) >= 0) {
|
||||
var iconName = __indexOf.call(iconData.iconList, fieldType);
|
||||
|
||||
iconObj.full = "fa-"+iconData.iconMap[iconName];
|
||||
iconObj.empty = "fa-"+iconData.iconMap[iconName]+"-o";
|
||||
if(iconName == "thumbs-up" || iconName == "thumbs-down"){
|
||||
iconObj.empty = "fa-"+iconData.iconMap[iconName].split("-")[0]+"-o-"+iconData.iconMap[iconName].split("-")[1];
|
||||
}else if(iconName == "Smile Outlined"){
|
||||
iconObj.empty = "fa-frown-o";
|
||||
}
|
||||
|
||||
return iconObj;
|
||||
} else {
|
||||
throw new Error("Error no shape of type: " + fieldType + " for rating input");
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority: 10000,
|
||||
terminal: true,
|
||||
scope: {
|
||||
ratingShapeIcon: '@'
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
var attrData = getRatingShape(attrs.ratingShapeIcon);
|
||||
|
||||
attrs.$set('icon-full', attrData.full);
|
||||
attrs.$set('icon-empty', attrData.empty);
|
||||
$compile(element)(scope);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'Auth',
|
||||
function ($http, TimeCounter, $filter, $rootScope, Auth) {
|
||||
return {
|
||||
|
@ -2083,6 +2145,44 @@ angular.module('forms').service('CurrentForm',
|
|||
);
|
||||
'use strict';
|
||||
|
||||
//Font-awesome-icon service used for fetching and mapping icon class names
|
||||
angular.module('forms').service('FontAwesomeIcons', ['$http', '$q', '$resource',
|
||||
function($http, $q, $resource){
|
||||
|
||||
var iconData = {};
|
||||
this.get = function(callback){
|
||||
|
||||
//Fetch icon list from font-awesome repo
|
||||
$http.get('https://raw.githubusercontent.com/FortAwesome/Font-Awesome/gh-pages/icons.yml').success(function (data) {
|
||||
var parsedData = jsyaml.load(data);
|
||||
|
||||
var parsedIconData = {
|
||||
iconMap: {},
|
||||
iconList: [],
|
||||
iconCategoryList: []
|
||||
};
|
||||
|
||||
var icons = parsedData.icons;
|
||||
|
||||
for (var i = 0; i < icons.length; i++) {
|
||||
parsedIconData.iconMap[icons[i].name] = icons[i].id;
|
||||
parsedIconData.iconList.push(icons[i].name);
|
||||
|
||||
for (var x = 0; x < icons[i].categories.length; x++) {
|
||||
if (!parsedIconData.iconCategoryList[icons[i].categories[x]]) parsedIconData.iconCategoryList[icons[i].categories[x]] = [];
|
||||
parsedIconData.iconCategoryList[icons[i].categories[x]].push(icons[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
callback(parsedIconData);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
|
||||
'use strict';
|
||||
|
||||
//TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server
|
||||
angular.module('forms').service('FormFields', [
|
||||
function() {
|
||||
|
@ -2166,7 +2266,7 @@ angular.module('forms').factory('Forms', ['$resource',
|
|||
}, {
|
||||
'query' : {
|
||||
method: 'GET',
|
||||
isArray: true,
|
||||
isArray: true
|
||||
//DAVID: TODO: Do we really need to get visible_form_fields for a Query?
|
||||
// transformResponse: function(data, header) {
|
||||
// var forms = angular.fromJson(data);
|
||||
|
@ -2182,7 +2282,6 @@ angular.module('forms').factory('Forms', ['$resource',
|
|||
method: 'GET',
|
||||
transformResponse: function(data, header) {
|
||||
var form = angular.fromJson(data);
|
||||
//console.log(form);
|
||||
|
||||
form.visible_form_fields = _.filter(form.form_fields, function(field){
|
||||
return (field.deletePreserved === false);
|
||||
|
|
6
public/dist/application.min.js
vendored
6
public/dist/application.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -79,7 +79,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
|||
}
|
||||
});
|
||||
|
||||
//Autosave Form when model (specificed in $attrs.autoSaveWatch) changes
|
||||
//Autosave Form when model (specified in $attrs.autoSaveWatch) changes
|
||||
$scope.$watch($attrs.autoSaveWatch, function(newValue, oldValue) {
|
||||
|
||||
newValue = angular.copy(newValue);
|
||||
|
|
|
@ -24,8 +24,25 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
|
|||
forcePlaceholderSize: true
|
||||
};
|
||||
|
||||
|
||||
console.log($scope.sortableOptions);
|
||||
/*
|
||||
** Setup Angular-Input-Star Shape Dropdown
|
||||
*/
|
||||
//Populate Name to Font-awesomeName Conversion Map
|
||||
$scope.select2FA = {
|
||||
'Heart': 'Heart',
|
||||
'Star': 'Star',
|
||||
'thumbs-up': 'Thumbs Up',
|
||||
'thumbs-down':'Thumbs Down',
|
||||
'Circle': 'Circle',
|
||||
'Square':'Square',
|
||||
'Check Circle': 'Checkmark',
|
||||
'Smile Outlined': 'Smile',
|
||||
'Hourglass': 'Hourglass',
|
||||
'bell': 'Bell',
|
||||
'Paper Plane': 'Paper Plane',
|
||||
'Comment': 'Chat Bubble',
|
||||
'Trash': 'Trash Can'
|
||||
};
|
||||
|
||||
//Populate AddField with all available form field types
|
||||
$scope.addField = {};
|
||||
|
@ -98,9 +115,17 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
|
|||
disabled: false,
|
||||
deletePreserved: false
|
||||
};
|
||||
// console.log('\n\n---------\nAdded field CLIENT');
|
||||
// console.log(newField);
|
||||
// newField._id = _.uniqueId();
|
||||
|
||||
if($scope.showAddOptions(newField)){
|
||||
newField.fieldOptions = [];
|
||||
newField.fieldOptions.push({
|
||||
'option_id' : Math.floor(100000*Math.random()),
|
||||
'option_title' : 'Option 0',
|
||||
'option_value' : 'Option 0'
|
||||
});
|
||||
}
|
||||
|
||||
console.log(newField);
|
||||
|
||||
// put newField into fields array
|
||||
if(modifyForm){
|
||||
|
@ -168,20 +193,17 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
|
|||
// add new option to the field
|
||||
$scope.addOption = function(field_index){
|
||||
var currField = $scope.myform.form_fields[field_index];
|
||||
console.log(field_index);
|
||||
console.log(currField);
|
||||
//console.log(field_index);
|
||||
//console.log(currField);
|
||||
|
||||
if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){
|
||||
if(!currField.fieldOptions) $scope.myform.form_fields[field_index].fieldOptions = [];
|
||||
if(!currField.fieldOptions){
|
||||
$scope.myform.form_fields[field_index].fieldOptions = [];
|
||||
}
|
||||
|
||||
var lastOptionID = 0;
|
||||
|
||||
if(currField.fieldOptions[currField.fieldOptions.length-1]){
|
||||
lastOptionID = currField.fieldOptions[currField.fieldOptions.length-1].option_id;
|
||||
}
|
||||
var lastOptionID = $scope.myform.form_fields[field_index].fieldOptions.length+1;
|
||||
|
||||
// new option's id
|
||||
var option_id = lastOptionID + 1;
|
||||
|
||||
var newOption = {
|
||||
'option_id' : Math.floor(100000*Math.random()),
|
||||
|
@ -219,7 +241,17 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
// decides whether field options block will be shown (true for dropdown and radio fields)
|
||||
$scope.showRatingOptions = function (field){
|
||||
if(field.fieldType === 'rating'){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('forms').directive('fieldIconDirective', function() {
|
||||
|
||||
|
||||
return {
|
||||
template: '<i class="{{typeIcon}}"></i>',
|
||||
restrict: 'E',
|
||||
|
@ -28,6 +28,6 @@ angular.module('forms').directive('fieldIconDirective', function() {
|
|||
'number': 'fa fa-slack'
|
||||
};
|
||||
$scope.typeIcon = iconTypeMap[$scope.typeName];
|
||||
},
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,7 +29,7 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
'number',
|
||||
'natural'
|
||||
];
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
templateUrl = templateUrl+type+'.html';
|
||||
}
|
||||
return $templateCache.get('../public/'+templateUrl);
|
||||
|
@ -38,7 +38,7 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
return {
|
||||
template: '<div>{{field.title}}</div>',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
scope: {
|
||||
field: '=',
|
||||
required: '&',
|
||||
design: '=',
|
||||
|
@ -46,7 +46,7 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
forms: '='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
|
||||
|
||||
$rootScope.chooseDefaultOption = scope.chooseDefaultOption = function(type) {
|
||||
if(type === 'yes_no'){
|
||||
scope.field.fieldValue = 'true';
|
||||
|
@ -99,7 +99,17 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
|||
}
|
||||
var template = getTemplateUrl(fieldType);
|
||||
element.html(template).show();
|
||||
$compile(element.contents())(scope);
|
||||
|
||||
if(scope.field.fieldType === 'rating'){
|
||||
//while($filter('toFaIcon')('Heart', false) == '-') {
|
||||
|
||||
//angular.element('input-stars').attr('icon-full', $filter('toFaIcon')('Heart', false));
|
||||
//angular.element('input-stars').attr('icon-empty', $filter('toFaIcon')('Heart', true));
|
||||
|
||||
//console.log($filter('toFaIcon')('Heart', false));
|
||||
//}
|
||||
}
|
||||
var output = $compile(element.contents())(scope);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// 'use strict';
|
||||
//
|
||||
// angular.module('forms').filter('toFaIcon', ['FontAwesomeIcons', '$timeout', function(FontAwesomeIcons, $timeout) {
|
||||
// var data = null, // DATA RECEIVED ASYNCHRONOUSLY AND CACHED HERE
|
||||
// serviceInvoked = false;
|
||||
//
|
||||
// var getRatingShape = function (fieldType, iconData) {
|
||||
// var iconObj = {
|
||||
// full: "",
|
||||
// empty: ""
|
||||
// };
|
||||
// var supported_fields = [
|
||||
// 'Heart',
|
||||
// 'Star',
|
||||
// 'thumbs-up',
|
||||
// 'thumbs-down',
|
||||
// 'Circle',
|
||||
// 'Square',
|
||||
// 'Check Circle',
|
||||
// 'Smile Outlined',
|
||||
// 'Hourglass',
|
||||
// 'bell',
|
||||
// 'Paper Plane',
|
||||
// 'Comment',
|
||||
// 'Trash'
|
||||
// ];
|
||||
// if (__indexOf.call(iconData.iconList, fieldType) >= 0) {
|
||||
//
|
||||
// iconObj.full = "fa-"+iconData.iconMap[fieldType];
|
||||
// iconObj.empty = "fa-"+iconData.iconMap[fieldType]+"-o";
|
||||
// if(fieldType == "thumbs-up" || fieldType == "thumbs-down"){
|
||||
// iconObj.empty = "fa-"+iconData.iconMap[fieldType].split("-")[0]+"-o-"+iconData.iconMap[fieldType].split("-")[1];
|
||||
// }else if(fieldType == "Smile Outlined"){
|
||||
// iconObj.empty = "fa-frown-o";
|
||||
// }
|
||||
//
|
||||
// return iconObj;
|
||||
// } else {
|
||||
// throw new Error("Error no shape of type: " + fieldType + " for rating input");
|
||||
// }
|
||||
// };
|
||||
//
|
||||
//
|
||||
// var realFilter = function initialFilter(shapeType, isEmpty) {
|
||||
// console.log('oldFilter');
|
||||
// if(isEmpty) return "fa-star-o"; // PLACEHOLDER
|
||||
// else return "fa-star";
|
||||
// };
|
||||
//
|
||||
// // function filterStub(shapeType, isEmpty){
|
||||
// // if( data === null ) {
|
||||
// // if (!serviceInvoked) {
|
||||
// // serviceInvoked = true;
|
||||
// //$timeout(function () {
|
||||
// FontAwesomeIcons.get().then(function (result) {
|
||||
// data = result;
|
||||
//
|
||||
//
|
||||
// realFilter = function newFilter(shapeType, isEmpty) {
|
||||
// console.log('newFilter');
|
||||
// var faData = getRatingShape(shapeType, data);
|
||||
// if (isEmpty) return faData.empty;
|
||||
// return faData.full;
|
||||
// };
|
||||
//
|
||||
// }, function (err) {
|
||||
// throw new Error("toShapeIcon Error: " + err.message || err);
|
||||
// });
|
||||
// /*realFilter = function newFilter(shapeType, isEmpty) {
|
||||
// console.log('newFilter');
|
||||
// if(isEmpty) return "fa-heart-o"; // PLACEHOLDER
|
||||
// else return "fa-heart";
|
||||
// }*/
|
||||
// //}, 1000);
|
||||
// // }
|
||||
// // return "-";
|
||||
// // //if(isEmpty) return "fa-star-o"; // PLACEHOLDER
|
||||
// // //else return "fa-star";
|
||||
// // } else return realFilter(shapeType, isEmpty);
|
||||
// // }
|
||||
// // filterStub.$stateful = true;
|
||||
// // return filterStub;
|
||||
//
|
||||
// function tempFilter(shapeType, isEmpty) {
|
||||
// return realFilter(shapeType, isEmpty);
|
||||
// }
|
||||
// tempFilter.$stateful = true;
|
||||
//
|
||||
// return tempFilter;
|
||||
//
|
||||
// }]);
|
|
@ -0,0 +1,46 @@
|
|||
// 'use strict';
|
||||
//
|
||||
// //Font-awesome-icon service used for fetching and mapping icon class names
|
||||
// angular.module('forms').service('FontAwesomeIcons', ['$http', '$q',
|
||||
// function($http, $q){
|
||||
//
|
||||
// var iconData = {};
|
||||
// this.get = function(callback){
|
||||
//
|
||||
// var deferred = $q.defer();
|
||||
//
|
||||
// //Fetch icon list from font-awesome repo
|
||||
// $http.get('https://raw.githubusercontent.com/FortAwesome/Font-Awesome/gh-pages/icons.yml').then(function (response) {
|
||||
// var parsedData = jsyaml.load(response.data);
|
||||
//
|
||||
// var parsedIconData = {
|
||||
// iconMap: {},
|
||||
// iconList: [],
|
||||
// iconCategoryList: []
|
||||
// };
|
||||
//
|
||||
// var icons = parsedData.icons;
|
||||
//
|
||||
// for (var i = 0; i < icons.length; i++) {
|
||||
// parsedIconData.iconMap[icons[i].name] = icons[i].id;
|
||||
// parsedIconData.iconList.push(icons[i].name);
|
||||
//
|
||||
// for (var x = 0; x < icons[i].categories.length; x++) {
|
||||
// if (!parsedIconData.iconCategoryList[icons[i].categories[x]]) parsedIconData.iconCategoryList[icons[i].categories[x]] = [];
|
||||
// parsedIconData.iconCategoryList[icons[i].categories[x]].push(icons[i].name);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// deferred.resolve(parsedIconData);
|
||||
// },
|
||||
// //Error Callback Function
|
||||
// function(data){
|
||||
// var error = response.data || "Request failed";
|
||||
// deferred.reject(error);
|
||||
// });
|
||||
//
|
||||
// return deferred.promise;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// ]);
|
|
@ -8,7 +8,7 @@ angular.module('forms').factory('Forms', ['$resource',
|
|||
}, {
|
||||
'query' : {
|
||||
method: 'GET',
|
||||
isArray: true,
|
||||
isArray: true
|
||||
//DAVID: TODO: Do we really need to get visible_form_fields for a Query?
|
||||
// transformResponse: function(data, header) {
|
||||
// var forms = angular.fromJson(data);
|
||||
|
@ -24,9 +24,9 @@ angular.module('forms').factory('Forms', ['$resource',
|
|||
method: 'GET',
|
||||
transformResponse: function(data, header) {
|
||||
var form = angular.fromJson(data);
|
||||
//console.log(form);
|
||||
|
||||
form.visible_form_fields = _.filter(form.form_fields, function(field){
|
||||
console.log(form.form_fields);
|
||||
form.visible_form_fields = _.filter(form.form_fields, function(field){
|
||||
return (field.deletePreserved === false);
|
||||
});
|
||||
return form;
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
{{index+1}}
|
||||
<i class="fa fa-angle-double-right" aria-hidden="true"></i>
|
||||
</small>
|
||||
{{field.title}}
|
||||
{{field.title}}
|
||||
<span class="required-error" ng-show="!field.required">optional</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-xs-12 field-input">
|
||||
<input-stars max="5"
|
||||
|
||||
<input-stars max="{{field.ratingOptions.steps}}"
|
||||
ng-init="field.fieldValue = 1"
|
||||
on-star-click="$root.nextField()"
|
||||
icon-full="fa-star"
|
||||
icon-full="{{field.ratingOptions.shape}}"
|
||||
icon-base="fa fa-3x"
|
||||
icon-empty="fa-star-o"
|
||||
icon-empty="{{field.ratingOptions.shape}}"
|
||||
ng-model="field.fieldValue"
|
||||
ng-model-options="{ debounce: 250 }"
|
||||
ng-required="field.required"
|
||||
|
|
|
@ -220,13 +220,13 @@
|
|||
|
||||
<div class="row"><br></div>
|
||||
|
||||
<div class="row description">
|
||||
<div class="row description" ng-hide="showRatingOptions(field)">
|
||||
<div class="col-md-4 col-sm-12">Description:</div>
|
||||
<div class="col-md-8 col-sm-12"><textarea type="text" ng-model="field.description" name="description{{field._id}}"value="{{field.description}}"></textarea> </div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-show="showAddOptions(field)"><br></div>
|
||||
<div class="row options" ng-show="showAddOptions(field)">
|
||||
<div class="row options" ng-if="showAddOptions(field)">
|
||||
<div class="col-md-4 col-xs-12">Options:</div>
|
||||
<div class="col-md-8 col-xs-12">
|
||||
<div ng-repeat="option in field.fieldOptions track by option.option_id" class="row">
|
||||
|
@ -244,6 +244,27 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row" ng-show="showRatingOptions(field)"><br></div>
|
||||
<div class="row" ng-if="showRatingOptions(field)">
|
||||
<div class="col-md-9 col-sm-9">Number of Steps:</div>
|
||||
<div class="col-md-3 col-sm-3">
|
||||
<input style="width:100%" type="number" ng-model="field.ratingOptions.steps" name="ratingOptions_steps{{field._id}}" ng-value="{{field.ratingOptions.steps}}" required>
|
||||
</div>
|
||||
<br>
|
||||
<div class="col-md-5 col-sm-9">Shape:</div>
|
||||
<div class="col-md-7 col-sm-3">
|
||||
<select style="width:100%" ng-model="field.ratingOptions.shape"
|
||||
value="{{field.ratingOptions.steps}}"
|
||||
name="ratingOptions_shape{{field._id}}" required>
|
||||
<option ng-repeat="shapeType in field.ratingOptions.validShapes"
|
||||
value="{{shapeType}}">
|
||||
{{select2FA[shapeType]}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row"><br></div>
|
||||
|
||||
<div class="row">
|
||||
|
|
Loading…
Reference in a new issue