whitef0x0/tellform

View on GitHub
app/models/form_field.server.model.js

Summary

Maintainability
C
7 hrs
Test Coverage
'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
    util = require('util'),
    timeStampPlugin = require('../libs/timestamp.server.plugin'),
    _ = require('lodash'),
    Schema = mongoose.Schema,
    LogicJumpSchema = require('./logic_jump.server.model'),
    tokgen = require('../libs/tokenGenerator');

var FieldOptionSchema = new Schema({
    option_id: {
        type: Number
    },

    option_title: {
        type: String
    },

    option_value: {
        type: String,
        trim: true
    }
});

var RatingFieldSchema = new Schema({
    steps: {
        type: Number,
        min: 1,
        max: 10
    },
    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
 */
function BaseFieldSchema(){
    Schema.apply(this, arguments);

    this.add({
        globalId: {
            type: String,
        },
        isSubmission: {
            type: Boolean,
            default: false
        },
        submissionId: {
            type: Schema.Types.ObjectId
        },
        title: {
            type: String,
            trim: true
        },
        description: {
            type: String,
            default: ''
        },

        logicJump: LogicJumpSchema,

        ratingOptions: RatingFieldSchema,
        fieldOptions: [FieldOptionSchema],
        required: {
            type: Boolean,
            default: true
        },
        disabled: {
            type: Boolean,
            default: false
        },

        deletePreserved: {
            type: Boolean,
            default: false
        },
        validFieldTypes: {
            type: [String]
        },
        fieldType: {
            type: String,
            enum: [
                'textfield',
                'date',
                'email',
                'link',
                'legal',
                'url',
                'textarea',
                'statement',
                'welcome',
                'thankyou',
                'file',
                'dropdown',
                'scale',
                'rating',
                'radio',
                'checkbox',
                'hidden',
                'yes_no',
                'natural',
                'stripe',
                'number'
            ]
        },
        fieldValue: Schema.Types.Mixed
    });

    this.plugin(timeStampPlugin, {
        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});
            console.error(error);
            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;
        }
    }


    //If field is multiple choice check that it has field
    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});
            console.error(error);
            return(next(error));
        }
    }

    return next();
});

//LogicJump Save
FormFieldSchema.pre('save', function(next) {
    if(!this.globalId){
        this.globalId = tokgen();
    }
    next();
});

//Submission fieldValue correction
FormFieldSchema.pre('save', function(next) {
    if(this.fieldType === 'dropdown' && this.isSubmission){
        this.fieldValue = this.fieldValue.option_value;
    }

    return next();
});


var Field = mongoose.model('Field', FormFieldSchema);
var RatingOptions = mongoose.model('RatingOptions', RatingFieldSchema);

module.exports = FormFieldSchema;